When selecting items programmatically in a ListView, I want the scroll to behave like native keyboard navigation — scroll only when the selected item is outside the visible area. Using listView.scrollTo(index) always repositions the view which feels unnatural. Here is my code:

public class Test1 extends Application { @Override public void start(Stage stage) { ListView<String> listView = new ListView<>(); listView.getItems().addAll( IntStream.rangeClosed(1, 30) .mapToObj(i -> "Item " + i) .collect(Collectors.toList()) ); listView.setPrefHeight(200); listView.getSelectionModel().select(0); Button up = new Button("Up"); Button down = new Button("Down"); up.setOnAction(e -> { int index = listView.getSelectionModel().getSelectedIndex(); if (index > 0) { listView.getSelectionModel().select(index - 1); scrollToIfNeeded(listView, index - 1); } }); down.setOnAction(e -> { int index = listView.getSelectionModel().getSelectedIndex(); if (index < listView.getItems().size() - 1) { listView.getSelectionModel().select(index + 1); scrollToIfNeeded(listView, index + 1); } }); HBox buttons = new HBox(10, up, down); VBox root = new VBox(10, listView, buttons); root.setPadding(new Insets(10)); stage.setScene(new Scene(root, 300, 300)); stage.show(); } private void scrollToIfNeeded(ListView<?> listView, int index) { VirtualFlow<?> flow = (VirtualFlow<?>) listView.lookup(".virtual-flow"); if (flow == null) { return; } var firstCell = flow.getFirstVisibleCell(); var lastCell = flow.getLastVisibleCell(); if (firstCell == null || lastCell == null) { return; } int first = firstCell.getIndex(); int last = lastCell.getBoundsInParent().getMaxY() > flow.getHeight() ? lastCell.getIndex() - 1 : lastCell.getIndex(); if (index < first) { listView.scrollTo(index); } else if (index >= last) { listView.scrollTo(index - (last - first)); } } public static void main(String[] args) { launch(args); } }

And this is the result:

As you can see, it fails for 7 because the selected cell should always be fully visible. Could anyone say how to do it?

SilverCube's user avatar

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.