ListView class

A scrollable, keyboard-navigable list of items, vertical by default or horizontal with scrollDirection.

Two ways to populate the list:

  • ListView(children: [...]) — eager. Every child widget is built upfront on each rebuild; the layout/paint pass only visits items that fit in the viewport. Best when you have a bounded set of widgets you already constructed.
  • ListView.builder(itemCount: N, itemBuilder: (context, index, highlighted) {}) — lazy. Only items currently within the viewport are mounted as element subtrees; items scroll into/out of the mounted set as the user navigates. Supports variable sizes along the scrolling axis. Best for long lists where most items are off-screen (file pickers, log viewers, completion menus).

When focused, the list handles its main-axis arrows (Up and Down, or Left and Right in a horizontal list), PageUp, PageDown, Home, End, and Enter:

  • The arrows move the current item by one, PageUp and PageDown by the number of items in view, and Home and End to the first and last item. A move reports onFocusedItemChanged and scrolls the item into view.
  • Enter or a completed click selects the current item via onSelect.
  • An arrow or page key pressed on the first item toward the start, or on the last toward the end, follows edgeBehavior: contain consumes the key, bubble returns it to the focus chain so an ancestor KeyBindings (e.g. one coordinating sidebar + main pane focus traversal) can react. From any other item, a page key stops at the first or last item.
  • A list without a current item (selectable: false, or a controller with no cursor) scrolls instead: the arrows by one cell and PageUp and PageDown by a viewport, following edgeBehavior once scrolled to an end, while Home and End jump to the start and end.

itemBuilder receives (context, index, highlighted) for each visible item. The current item remains highlighted when keyboard focus leaves the list. The controller's ListController.currentIndex identifies that item. Setting it moves the cursor without selecting an item or taking focus.

All constructors apply the theme's selection style to the current row's text. Plain Text children need no cursor styling. Explicit child styles override that default; the builder flag is available for custom decoration.

Inheritance
Available extensions

Constructors

ListView({Key? key, ListController? controller, FocusNode? focusNode, required List<Widget> children, bool autofocus = false, bool selectable = true, EdgeBehavior edgeBehavior = EdgeBehavior.bubble, void onSelect(int index)?, void onFocusedItemChanged(int index)?, bool scrollbar = false, Axis scrollDirection = Axis.vertical, bool addRepaintBoundaries = true})
Eager constructor: build all items upfront from a fixed list of widgets. Use when you have a bounded set of widgets already constructed. The current row is highlighted automatically.
const
ListView.builder({Key? key, ListController? controller, FocusNode? focusNode, required int itemCount, required Widget itemBuilder(BuildContext, int, bool), ListItemKeyBuilder? itemKeyBuilder, bool autofocus = false, bool selectable = true, EdgeBehavior edgeBehavior = EdgeBehavior.bubble, void onSelect(int index)?, void onFocusedItemChanged(int index)?, bool scrollbar = false, Axis scrollDirection = Axis.vertical, bool addRepaintBoundaries = true})
Lazy constructor: build items on demand by index, mount only the visible ones. Each item builder invocation receives a highlighted flag for styling the current row.
const
ListView.separated({Key? key, ListController? controller, FocusNode? focusNode, required int itemCount, required Widget itemBuilder(BuildContext, int, bool), required Widget? separatorBuilder(BuildContext, int), ListItemKeyBuilder? itemKeyBuilder, bool autofocus = false, bool selectable = true, EdgeBehavior edgeBehavior = EdgeBehavior.bubble, void onSelect(int index)?, void onFocusedItemChanged(int index)?, bool scrollbar = false, Axis scrollDirection = Axis.vertical, bool addRepaintBoundaries = true})
Lazy constructor with separators — the TUI analogue of Flutter's ListView.separated. separatorBuilder is called for each gap i — the space between item i and item i + 1, so 0 <= i <= itemCount - 2 — and may return null to omit that gap's separator (e.g. a day divider shown only when the day actually changes).
const

Properties

addRepaintBoundaries → bool
Whether each item gets its own RepaintBoundary, so an update inside one item (a row's setState, a line of streaming output) repaints only that item rather than the whole list. Items stay interactive and accessible either way.
final
autofocus → bool
Whether to request focus on first mount.
final
children → List<Widget>?
Pre-built widgets (eager form). Mutually exclusive with itemCount / itemBuilder.
final
controller → ListController?
External controller. If null, the widget creates its own and disposes it on unmount.
final
edgeBehavior → EdgeBehavior
How main-axis arrows and wheel gestures behave at an edge. Cross-axis input can reach other controls or a surrounding scroll view.
final
effectiveItemCount → int
Effective number of items, regardless of which constructor was used. Returns children!.length for eager, itemCount! for lazy.
no setter
focusNode → FocusNode?
External FocusNode. Provide one when a parent needs to drive focus (e.g. Tab cycling between sidebar and main pane). If null, the widget creates its own and disposes it on unmount.
final
hashCode → int
The hash code for this object.
no setterinherited
itemBuilder → Widget Function(BuildContext context, int index, bool highlighted)?
Per-index widget builder (lazy form). Mutually exclusive with children. Invoked with (context, index, highlighted).
final
itemCount → int?
Number of items (lazy form). Mutually exclusive with children.
final
itemKeyBuilder → ListItemKeyBuilder?
Returns a stable key for the data item at each index. Supply it when items can move (prepends, removals, filters, reorders) so the current item, the scroll position, and the state of mounted items follow each item rather than its index. Keys must be unique within the list and have stable equality and hash codes; a duplicate key throws a StateError.
final
key → Key?
finalinherited
onFocusedItemChanged → void Function(int index)?
Reports user input moving the cursor to a different item.
final
onSelect → void Function(int index)?
Selects an item on Enter or a completed click, including repeated choices. Browsing, scrolling, and controller writes do not call this. Empty lists and lists without a cursor cannot select an item.
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
scrollbar → bool
When true, wrap the list in a Scrollbar gutter that reflects the visible item range and lets the mouse drag/click to scroll. A one-line opt-in: the bar shares this list's controller, so there is nothing extra to wire. See Scrollbar.list.
final
scrollDirection → Axis
Layout and scrolling axis. Items are measured at their natural extent along this axis and constrained to the viewport on the other axis.
final
selectable → bool
Whether the list owns a row cursor and selects rows with click or Enter. False keeps it scrollable without a row cursor. Interactive child widgets keep their own input behavior.
final
separatorBuilder → Widget? Function(BuildContext context, int index)?
Per-gap separator builder (ListView.separated form). Called with (context, i) for the gap between item i and item i + 1; may return null to omit that separator. Null for the eager and ListView.builder forms.
final

Methods

animate({Duration? duration, Curve? curve, Object? trigger, bool repeat = false}) → Animate

Available on Widget, provided by the AnimateExtension extension

Starts an Animate chain over this widget. duration / curve apply to the whole chain. With no trigger it plays on mount; with a non-null trigger it rests on mount and replays whenever the token changes.
createElement() → StatefulElement
Creates the Element that will mount this widget into the tree.
inherited
createState() → State<ListView>
Creates the mutable state for this widget at the current location in the tree. Called exactly once per StatefulElement instance.
override
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() → String
A string representation of this object.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited