Skip to main content

GridView

Purpose​

Cells in equal columns: a fixed count, as many as fit, or virtualised.

Signature​

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

impl GridView {
pub fn new(columns: usize) -> Self;
pub fn extent<W: Widget<Msg> + 'static>(
max_tile_width: f32,
count: usize,
build: impl Fn(usize) -> W + 'static,
) -> Self;
pub fn builder<W: Widget<Msg> + 'static>(
columns: usize,
count: usize,
build: impl Fn(usize) -> W + 'static,
) -> Self;
}

Example​

Rendered preview of the GridView demo

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

//! `GridView` — cells in equal columns, placed row by row: a fixed number of columns,
//! as many as fit a maximum width, or a virtualised grid that only builds the visible
//! rows.

use frus::{Center, Color, Colors, Container, GridView, Text, Widget};

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

pub fn example() -> Box<dyn Widget> {
sections(vec![
// A fixed number of columns. `aspect` makes every tile the same shape
// (width / height); without it a row is as tall as its tallest cell.
Box::new(section(
"Three columns, square tiles",
Container::new().width(320.0).child((0..9).fold(
GridView::new(3).width(320.0).gap(8.0).aspect(1.0),
|grid, i| grid.cell(tile(i)),
)),
)),
// `extent` takes a maximum tile width and works out how many columns fit — more
// on a wide window, fewer on a phone, with no breakpoints. Its cells are built
// from their index once the width is known.
Box::new(section(
"As many columns as fit (tiles ≤ 72 px)",
GridView::extent(72.0, 12, tile).gap(6.0).aspect(1.0),
)),
// `builder` virtualises: a thousand tiles, only the visible rows built. It
// scrolls by itself, so it needs a height here.
Box::new(section(
"1 000 tiles, virtualised",
GridView::builder(4, 1000, tile)
.gap(4.0)
.tile_height(56.0)
.width(320.0)
.height(240.0),
)),
])
}

/// A numbered, coloured tile. A plain function of the index, which is what the grids
/// that build their cells late (`extent`, `builder`) need.
fn tile(i: usize) -> Container {
const HUES: [&str; 5] = ["#6366F1", "#0EA5E9", "#10B981", "#F59E0B", "#EF4444"];
Container::new()
.radius(6.0)
.color(Color::hex(HUES[i % HUES.len()]))
.child(Center::new(
Text::new(format!("{}", i + 1)).color(Colors::WHITE),
))
}

Properties​

MethodArgumentEffect
.gap()gap: f32Spacing between cells (rows and columns), in logical pixels.
.row_gap()gap: f32Spacing between rows only, in logical pixels. Overrides GridView::gap down the grid and leaves it alone across.
.column_gap()gap: f32Spacing between columns only, in logical pixels. Overrides GridView::gap across the grid and leaves it alone down.
.aspect()ratio: f32Gives every cell the same shape: a width / height ratio, so 1.0 is a square tile, 1.5 a landscape one and 0.75 a portrait one.
.tile_height()height: f32—
.width()width: f32Sets the width, in logical pixels.
.height()height: f32Sets the height, in logical pixels.
.flex()grow: f32Flex growth factor along the parent's main axis.
.physics()physics: crate::physics::ScrollPhysicsOverrides how the grid behaves at its edges and after a fling (milestone 655); see crate::scroll::SingleChildScrollView::physics.
.primary()primary: boolA primary view is always scrollable unless physics says otherwise: a drag moves it, and bounces or glows at its edge, even when everything is in sight, so a page that fits still answers the finger as a page.
.on_scroll()on_scroll: impl Fn(crate::ScrollPosition) -> R + 'staticSays where this grid is whenever it moves. A gallery that fetches the next page when the end comes into view is what a grid wants it for; see crate::ScrollPosition::remaining_y, and GridView::notify_every for how often that question is worth asking.
.notify_every()px: f32Reports no more often than every px of movement — and always reports where it comes to rest, however short the last step was.
.cell()cell: impl Widget<Msg> + 'staticAdds a cell, placed automatically in the grid.

Behaviour​

A grid of columns equal columns.

See also​

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