Skip to main content

ListView

Struct ListView 

Source
pub struct ListView<State>
where State: 'static,
{ /* private fields */ }
Expand description

A declarative, virtualized vertical list. See the module docs.

builder is a pure function of the item index; it is retained (an Rc) so the previous frame’s view for a surviving index can be reconstructed during reconciliation. All rows share the uniform, required item_extent.

Implementations§

Source§

impl<State> ListView<State>
where State: 'static,

Source

pub fn builder( item_count: usize, item_extent: f64, builder: impl Fn(usize) -> AnyView<State> + 'static, ) -> ListView<State>

Create a virtualized list of item_count rows, each item_extent logical pixels tall, whose row at index is produced by builder.

The builder returns an AnyView (rows may differ in concrete view type); spell each row with frust_core::any. Panics if item_extent is not positive (the uniform extent is the virtualization fast path; a zero/negative extent has no well-defined window).

§Contract

Rows are reconciled by raw item index, not by a stable key. This is safe for append-only, truncate-only, and full-replace data, but a mid-list insert/remove/reorder silently reattaches a retained row’s state to different content at the same index. See the module docs’ Row identity section for the full rule, and ListView::builder_keyed for the stable-key alternative that survives a mid-list mutation.

Source

pub fn builder_keyed( item_count: usize, item_extent: f64, key_of: impl Fn(usize) -> ChildKey + 'static, builder: impl Fn(usize) -> AnyView<State> + 'static, ) -> ListView<State>

Create a virtualized list whose rows are reconciled by the stable key key_of(index) instead of by raw item index — the mid-list-mutation-safe counterpart of ListView::builder, everything else identical.

key_of returns the identity of the row at an item index (a ChildKey, built from any Hash value — an item id, a name — via ChildKey::new/.into()); it is called once per materialized slot per frame, never item_count times, and must be a pure function of the index over one frame’s data, exactly like builder. Panics if item_extent is not positive, like ListView::builder.

ⓘ
ListView::builder_keyed(
    rows.len(),
    56.0,
    move |i| ChildKey::new(rows[i].id),
    move |i| any::<AppState, _>(row_view(&rows[i])),
)
§Contract

A row whose key stays in the window keeps its live widget — and so its entire retained state — even when an insert/remove/reorder moves it to a different index; a key that leaves the window (or the data) is torn down, and a key entering is built fresh. Keys must be unique within a window: a duplicate trips a debug_assert! and, in release, hands the live row to the first slot claiming the key while later duplicates build fresh (no panic, but which row keeps its state is arbitrary). See the module docs’ Row identity section.

Source

pub fn estimated_item_extent(self, estimate_px: f64) -> ListView<State>

Let rows size themselves, taking estimate_px as the assumed extent of every row that has not been measured yet — variable-extent mode, available on ListView::builder_keyed lists only.

A materialized row is laid out under the list’s width with unbounded height and reports whatever height it wants; that height is cached under the row’s stable key and used from then on for window math, the scroll extent, and the row’s content position. Unmeasured rows (everything not yet laid out) count as estimate_px, so the scroll range converges on the true content height as the user visits rows. The constructor’s item_extent is unused in this mode — pass the same value as the estimate for clarity.

ⓘ
ListView::builder_keyed(rows.len(), 72.0, key_of, builder)
    .estimated_item_extent(72.0)
§Contract

Keyed lists only. A measured extent is cached under row identity, so it must move with the row; a positional list has no identity to cache under. Calling this on a ListView::builder list trips a debug_assert! and is inert in release — the list keeps its closed-form uniform extent rather than panicking live (the same shape as the duplicate-key tripwire, see the module docs’ Variable extents section for why this is a debug_assert and not type-state). Panics if estimate_px is not positive, like the constructors’ item_extent.

Source

pub fn on_near_start<F>(self, callback: F, threshold_px: f64) -> ListView<State>
where F: Fn(&mut State) + 'static,

Fire callback when the scrolled window comes within threshold_px of content start — the load-older edge for a newest-at-bottom chat list.

The callback is edge-triggered: it fires once per approach and rearms only after the user scrolls away past 2 × threshold_px (or the item count changes). Drag, wheel, and fling motion all observe it — fling motion is driven at paint time (no frust_core::EventCtx), so a fling-triggered fire is recorded and delivered on the next event, one event late; a Cancel clears a pending fire without invoking the callback.

Source

pub fn on_near_end<F>(self, callback: F, threshold_px: f64) -> ListView<State>
where F: Fn(&mut State) + 'static,

Fire callback when the scrolled window comes within threshold_px of content end — the load-newer edge for an infinite-scroll-downward list.

Mirrors ListView::on_near_start exactly, measured from content end instead of start: edge-triggered, firing once per approach and rearming only after the user scrolls back past 2 × threshold_px away from the end (or the item count changes). Drag, wheel, and fling motion all observe it — a fling-triggered fire is recorded and delivered on the next event, one event late; a Cancel clears a pending fire without invoking the callback.

Source

pub fn on_refresh_release<F>(self, callback: F) -> ListView<State>
where F: Fn(&mut State) + 'static,

The pull-to-refresh trigger: fires on pointer Up when the list was pulled past the top by more than REFRESH_TRIGGER_PX (post-resistance) — the same name, signature, and threshold behavior as crate::ScrollView::on_refresh_release, so a screen can swap between the two containers without relearning the contract. Never fires on a Cancel, and a bottom overscroll can never trigger it (only a past-top pull can). See the module docs’ Overscroll and pull-to-refresh section.

Source

pub fn physics(self, physics: impl ScrollPhysics + 'static) -> ListView<State>

Install a custom ScrollPhysics strategy — the same seam crate::ScrollView::physics installs, sharing scroll.rs’s resistance/trigger/settle constants and this crate’s crate::physics::parity/RubberBand implementations.

use frust_widgets::{ListView, NeverScrollable, text};
let view: ListView<()> = ListView::builder(3, 40.0, |i| {
    frust_core::any::<(), _>(text(i.to_string()))
})
.physics(NeverScrollable::new());
§Build/rebuild semantics

Identical to crate::ScrollView::physics: a view built (or rebuilt) with .physics(...) reinstalls it on the widget every time; a view built (or rebuilt) without it leaves the widget’s currently-installed physics untouched (a fresh build still starts at crate::physics::default_physics, the widget’s own constructor default).

Defaults to the platform-adaptive physics (crate::physics::default_physics — Android clamping, elsewhere bouncing) if never called; .physics(RubberBand::new()) is how an app asks for the pre-seam rubber-band feel instead.

Source

pub fn overscroll_effect(self, effect: OverscrollEffect) -> ListView<State>

Select how past-edge pull is visualized. See OverscrollEffect (crate::physics::effect) for the full contract — the same selector crate::ScrollView::overscroll_effect installs.

use frust_widgets::{ListView, OverscrollEffect, text};
let view: ListView<()> = ListView::builder(3, 40.0, |i| {
    frust_core::any::<(), _>(text(i.to_string()))
})
.overscroll_effect(OverscrollEffect::Stretch);

Plain view-owned data, unlike ListView::physics: every build/rebuild carries the current value down to ListViewWidget::effect unconditionally.

Defaults to the effect paired with the platform’s default physics (crate::physics::default_overscroll_effect): the M3E OverscrollEffect::Stretch on Android, translate overscroll (OverscrollEffect::Translate) everywhere else.

Source§

impl<State> ListView<State>
where State: 'static,

This impl block contains no public items.

The reconciliation half of View::rebuild, split per identity mode. See the module docs’ Row identity section for which one runs when.

Trait Implementations§

Source§

impl<State> View<State> for ListView<State>
where State: 'static,

Source§

type Element = ListViewWidget

The retained widget this view produces.
Source§

fn build(&self, ctx: &mut BuildCtx<'_>) -> ListViewWidget

Materialise a fresh widget for this view.
Source§

fn rebuild( &self, prev: &ListView<State>, element: &mut ListViewWidget, ctx: &mut BuildCtx<'_>, ) -> ChangeFlags

Reconcile prev (the previous view of the same type) against the live element, mutating it in place and reporting what changed.
Source§

fn teardown(&self, element: &mut ListViewWidget, ctx: &mut BuildCtx<'_>)

Tear down element when this view is being removed. Read more
Source§

fn message(&self, _element: &mut Self::Element, _state: &mut State)

Deliver an event message to this view, mutating application state. Read more

Auto Trait Implementations§

§

impl<State> !RefUnwindSafe for ListView<State>

§

impl<State> !Send for ListView<State>

§

impl<State> !Sync for ListView<State>

§

impl<State> !UnwindSafe for ListView<State>

§

impl<State> Freeze for ListView<State>
where Rc<dyn Fn(usize) -> AnyView<State>>: Freeze, Option<Rc<dyn Fn(&mut State)>>: Freeze,

§

impl<State> Unpin for ListView<State>
where Rc<dyn Fn(usize) -> AnyView<State>>: Unpin, Option<Rc<dyn Fn(&mut State)>>: Unpin,

§

impl<State> UnsafeUnpin for ListView<State>
where Rc<dyn Fn(usize) -> AnyView<State>>: UnsafeUnpin, Option<Rc<dyn Fn(&mut State)>>: UnsafeUnpin,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

Source§

fn simd_from(_simd: S, value: T) -> T

Source§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

Source§

fn simd_into(self, simd: S) -> T

Source§

impl<T> StorageAccess<T> for T

Source§

fn as_borrowed(&self) -> &T

Borrows the value.
Source§

fn into_taken(self) -> T

Takes the value.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more