Skip to main content

PageView

Purpose​

A scrollable that always comes to rest on a page.

Signature​

pub struct PageView<Msg = crate::callback::Callback> { .. }

impl PageView {
pub fn new<W: Widget<Msg> + 'static>(
count: usize,
build: impl Fn(usize) -> W + 'static,
) -> Self;
}

Example​

Rendered preview of the PageView demo

From frus-examples/widgets/src/features/scrolling/widgets/pageview.rs:

//! `PageView` — a scrollable that always comes to rest on a page: onboarding screens, a
//! photo gallery, swipeable panels. Pages are built on demand from their index.

use frus::{Align, Axis, Center, Color, Colors, Column, Container, PageView, Text, Widget};

use crate::common::shared::{section, sections};

const HUES: [&str; 5] = ["#6366F1", "#0EA5E9", "#10B981", "#F59E0B", "#EF4444"];

pub fn example() -> Box<dyn Widget> {
Box::new(frus::component(|cx| {
let page = cx.use_state(|| 0usize);

// `on_page_changed` reports the page a reader would name as the finger moves,
// so a caption follows the picture rather than trailing it.
let follow = page.clone();
let full = PageView::new(HUES.len(), |i| card(i, "Swipe sideways"))
.height(180.0)
.width(320.0)
.on_page_changed(move |i: usize| follow.set(i));

// `viewport_fraction` below 1 shows a sliver of the neighbours — a hint that
// there is more to swipe to.
let peek = PageView::new(HUES.len(), |i| {
Container::new().padding(6.0).child(card(i, "Peek"))
})
.viewport_fraction(0.8)
.height(160.0)
.width(320.0);

// Pages can run down instead of across.
let vertical = PageView::new(HUES.len(), |i| card(i, "Swipe up"))
.axis(Axis::Vertical)
.height(160.0)
.width(320.0);

sections(vec![
Box::new(section(
"Full pages",
Column::new()
.spacing(8.0)
.cross_axis_alignment(Align::Start)
.child(full)
.child(
Text::new(format!("Page {} of {}", page.get() + 1, HUES.len()))
.color(cx.theme().muted),
),
)),
Box::new(section("Neighbours peeking in", peek)),
Box::new(section("Vertical", vertical)),
])
}))
}

/// One page: a plain widget made from its index.
fn card(i: usize, hint: &str) -> Container {
Container::new()
.radius(12.0)
.color(Color::hex(HUES[i % HUES.len()]))
.child(Center::new(
Text::new(format!("{} · page {}", hint, i + 1))
.size(18.0)
.color(Colors::WHITE),
))
}

Properties​

MethodArgumentEffect
.axis()axis: AxisLays the pages out along axis. Only Axis::Horizontal and Axis::Vertical mean anything here: a page view pages one way.
.viewport_fraction()fraction: f32The fraction of the viewport one page occupies; 1.0 — the default — makes each page fill it.
.pad_ends()pad: boolWhether there is room at both ends of the content, so that the first and last pages come to rest centred in the viewport. On by default, and nil at the default viewport_fraction of one, where a page already fills the viewport and there is nothing to centre.
.page_snapping()snapping: boolWhether a release comes to rest on a page. On by default — it is what makes this a page view rather than a scroll.
.reverse()—Pages from the far end: page 0 sits at the edge the axis finishes at — the right of a horizontal view, the bottom of a vertical one — page 1 before it, and the view opens there.
.page()page: usizeThe page to show.
.on_page_changed()message: impl Fn(usize) -> R + 'staticThe message sent when the page a reader would name changes — mid-drag, as soon as the rounding tips, not once the motion has settled. A title above a gallery should follow the picture, not trail it.
.physics()physics: ScrollPhysicsOverrides how the view behaves at its edges; see crate::SingleChildScrollView::physics. The fling is a page view's own business either way.
.width()width: f32Sets the viewport width, in logical pixels.
.height()height: f32Sets the viewport height, in logical pixels.
.flex()grow: f32Flex growth factor along the parent's main axis.

Behaviour​

A scrollable that rests only on page boundaries.

See also​

  • ListView: a virtualised list: only the visible rows are built.
  • GridView: cells in equal columns: a fixed count, as many as fit, or virtualised.
  • CarouselView: one slide at a time between arrows, controlled by the app.
  • ReorderableList: a list whose rows can be dragged into a new order.
  • Dismissible: swipe a row aside to archive or delete it.
  • The guide: Lists and grids
  • API reference: PageView

Source: crates/frus-widgets/src/pageview.rs @ e6fba33f5b42