Search code examples
listviewjavafxgestures

JavaFX ListView with touch events for scrolling up and down


I would like to implement a scrollable ListView with gestures, just like in mobiles and tablets, to scroll up and down my list with a finger. But my current list selects an item as soon as I click down on the list. How can I achieve this? I couldn't find any example at the Oracle tutorials.

private ObservableList<Document> items = FXCollections.observableArrayList();
@FXML ListView<Document> listView;

{
    ...

    listView.setItems(items);
    listView.getStylesheets().add("style/listview.css");
    listView.setStyle("-fx-background-insets: 0 ;"); // remove 1px border of listview container

    listView.setCellFactory(new Callback<ListView<Document>, ListCell<Document>>() {
        @Override
        public ListCell<Document> call(ListView<Document> listView) {
            return new DocumentArrayAdapter();
        }
    });  

    ...
}

public void loadListView(List<Document> ldoc){
    if (!ldoc.isEmpty()){
        items.addAll(ldoc);
    }
}

Solution

  • This is what I've made

    public class CustomListCell extends ListCell<Document>{
    
    private double lastYposition = 0;
    
    public CustomListCell(){
    
        setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                lastYposition = event.getSceneY();
            }
        });
    
        setOnMouseDragged(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                double newYposition = event.getSceneY();
                double diff = newYposition - lastYposition;
                lastYposition = newYposition;
                CustomScrollEvent cse = new CustomScrollEvent();
                cse.fireVerticalScroll((int)diff, DocumentArrayAdapter.this, (EventTarget) event.getSource());
            }
        });  
    

    and

    package myproject.utils;
    
    import javafx.event.Event;
    import javafx.event.EventTarget;
    import javafx.scene.input.ScrollEvent;
    
    public class CustomScrollEvent {
    
    public void fireVerticalScroll(int deltaY, Object source, EventTarget target){
    
        ScrollEvent newScrollEvent = null;
        newScrollEvent = new ScrollEvent(source,
                   target,
                   ScrollEvent.SCROLL,
                   0,
                   0,
                   0,
                   0,
                   false,
                   false,
                   false,
                   false,
                   false,
                   false,
                   0,
                   deltaY,
                   0,
                   0,
                   ScrollEvent.HorizontalTextScrollUnits.CHARACTERS,
                   0,
                   ScrollEvent.VerticalTextScrollUnits.NONE,
                   deltaY,
                   0,
                   null);
    
            Event.fireEvent(target, newScrollEvent);
    }
    }
    

    Although I've implemented the listener in my own ListCell, I guess it would also work implementing the listeners directly at the ListView, with listView.setOnMousePressed and listView.setOnMouseDragged