pub fn virtual_list<E: IntoElement>(
count: impl Fn() -> usize + 'static,
row_height: f32,
row: impl Fn(usize) -> E + 'static,
) -> Element<ScrollView>Expand description
Creates a list of count rows of one height inside a scroll view, with
only the rows near the viewport mounted.
The returned element is the scroll view; give it a height, either directly
or through a parent that sizes it. It scrolls with the wheel like any
scroll view, and it shows a thumb for the whole list, because its content
is a spacer panel as tall as count rows, whatever the mounted window is.
The rows are built by row, which receives the row’s index. A row is
built once, the first time its index enters the window, and it stays
mounted, with its reactive state, until the window moves past it. Content
that changes while a row stays mounted must come from the signals that row
reads: a new value for an index that never left the window reaches no
mounted row. The row should keep to row_height; a taller one overlaps
the row below it, and a shorter one leaves the spacer’s background showing.
count runs inside a binding, so only the signals it reads remount the
window. A shrinking count clamps the offset, and the window follows on the
frame after the new height has been measured.
The list owns its scroll offset; do not call
ScrollExt::offset on the returned view,
because the window would follow the signal the list started with while the
view scrolls by the one the call installs.
row_height must be positive and finite. Anything else mounts no rows,
and a list built that way shows an empty view.
use smudge_core::reactive::{RwSignal, prelude::*};
use smudge_core::style::px;
use smudge_text::label;
use smudge_widgets::virtual_list;
let count = RwSignal::new(100_000);
let list = virtual_list(
move || count.get(),
24.0,
|index| label(format!("Row {index}")),
)
.height(px(480.0));