If I create a ListView:
new ListView<>(FXCollections.observableArrayList("1", "2", "3"))
I would expect it to create a ListView with 3 rows. But it doesn't. It creates a ListView of 17 or so rows. Is there a way to tell ListView to always be the height such that whatever items are in it are always shown but no blank rows?
Having it auto width would also be useful, so it's always as wide as the widest row.
One purpose of this is that then it could be used in a ScrollPane. I know it has its own scrollbars, but they don't offer sufficient control.
Unfortunately there is not a nice, clean size Property of an ObservableList for us to bind to. Instead, it's doable by adding a ListChangeListener on the list, at least, that's how I've done it in the past. By default the size of each row should be 24px, and we need an extra pixel on the top and bottom for the ListView's edges. Otherwise we still have the ListView's scroll bar showing. First we'll create the ObservableList and the ListView, and set the initial height of the ListView:
Now we have to add a ListChangeListener to the ObservableList. When the list changes, we simply change the set height of the ListView to match the new number of rows. If we know that we are never going to add or remove items from the ObservableList that is backing the ListView, then we can exclude the listener. Again, the height is the number of rows times the height per row plus two extra pixels for the borders:
References: JavaFX ListView Documentation, JavaFX ObservableList Documentation
I found a relatively easy though still slightly hacky solution which works under the assumption that all non-empty cells have the same height: instead of parsing css or some such, add an
InvalidationListener
to yourlistView.getItems()
; the first time your items list becomes non-empty, you recursively go through theListView
s children until you find an instance ofListCell
where!cell.isEmpty()
, and store the value ofcell.getHeight()
. Be sure to wrap that code in aPlatform.runLater()
so that it gets executed once theListView
layouting is done. Once you have that height, you multiply it withlistView.getItems().size()
and calllistView.setMaxHeight
with the resulting value (still inside theInvalidationListener
).I based my answer on the answers provided by @scribbleslims and @Alexandre Mazari
listView.setPrefHeight(listView.getItems().size() * LIST_CELL_HEIGHT);
You have to define
LIST_CELL_HEIGHT
on your own.In my case, I used 29.501.