Skip to main content

IndexedStack

Function IndexedStack 

Source
pub fn IndexedStack<State: 'static, M>(
    index: Option<usize>,
    children: impl ViewSeq<State, M>,
) -> IndexedStackView<State>
Expand description

Keep every child of children mounted and show only the one at index.

children is any ViewSeq: a Vec/array of views, a tuple of mixed view types (positional, up to 12 and nestable), an Option (None drops the slot), or views(iter) for an iterator. Every element is erased once, here. An index that is None or out of range selects nothing: the stack paints nothing, routes no input and exposes no accessibility node, while every child stays mounted.

§Reach follows the selection (R23)

Only the selected child is reachable. Input events go to it alone, the accessibility tree contains it alone, and a navigator anywhere inside an unselected child reports back_interest == false, the same rule that silences a navigator on a covered navigator page. The stack does this by installing one page-reach cell per child, true only for the selected child, and only while the stack itself is reachable. A stack built on a navigator page that later gets covered therefore leaves every tab navigator unreachable, at any nesting depth. Cells are rewritten on every rebuild, before the children are reconciled, so a nested navigator always reads the value for the selection it is being rebuilt under.

Broadcast events (housekeeping, overlay and drop-end notifications) are not user input and go to every child, as they do for the navigator’s pages: a navigator in an unselected tab may hold a queued pop result that must still flush on the frame that produced it.

§Page-switch contract

When the selected index changes, the outgoing child is handled the way a navigator handles a covered page, in this order: an in-flight pointer capture receives a synthetic Cancel (so it never fires on a later Up), its focus flag is cleared, and, if that child held focus on the live focus chain, the next paint publishes a cleared IME surface so the platform keyboard hides. A child that never held focus publishes nothing, so a text field elsewhere in the tree keeps its session. The incoming child is not focused automatically.

§Layout

Every child is laid out under the stack’s loosened constraints at the stack origin, and the stack takes the size of its largest child, clamped to its constraints. This matches Flutter’s IndexedStack: the stack does not change size when the selection changes.

use frust_widgets::{IndexedStack, IndexedStackView, Stack, indexed_stack, text};
// Mixed child types: a tuple, no `any(..)` needed.
let tabs = IndexedStack(Some(1), (text("home"), Stack((text("feed"), text("badge")))));
// The fluent form.
let fluent = indexed_stack(Some(0)).child(text("home")).child(text("search"));