Skip to main content

Overview

ListView is a scrollable list of controls arranged linearly. It is the most commonly used scrolling control and displays its children one after another in the scroll direction. In the cross axis, the children are required to fill the ListView. ListView is very efficient and can handle thousands of items through lazy rendering when build_controls_on_demand is enabled.

Basic Example

import flet as ft

def main(page: ft.Page):
    page.add(
        ft.ListView(
            controls=[ft.Text(f"Item {i}") for i in range(1, 6)],
        )
    )

ft.app(main)

Class Definition

class ListView(LayoutControl, ScrollableControl, AdaptiveControl):
    controls: list[Control] = field(default_factory=list)
    horizontal: bool = False
    reverse: bool = False
    spacing: Number = 0
    item_extent: Optional[Number] = None
    first_item_prototype: bool = False
    prototype_item: Optional[Control] = None
    divider_thickness: Number = 0
    padding: Optional[PaddingValue] = None
    clip_behavior: ClipBehavior = ClipBehavior.HARD_EDGE
    semantic_child_count: Optional[int] = None
    cache_extent: Optional[Number] = None
    build_controls_on_demand: bool = True

Properties

controls

controls
list[Control]
default:"[]"
A list of controls to display inside ListView. Controls are arranged linearly in the scroll direction.

horizontal

horizontal
bool
default:"False"
Whether to layout the controls horizontally.
  • False (default) - Vertical scrolling list
  • True - Horizontal scrolling list

reverse

reverse
bool
default:"False"
Whether the scroll view scrolls in the reading direction.
  • If the reading direction is left-to-right and horizontal is True, the scroll view scrolls from left to right when reverse is False and from right to left when reverse is True.
  • If horizontal is False, the scroll view scrolls from top to bottom when reverse is False and from bottom to top when reverse is True.

spacing

spacing
Number
default:"0"
The height (or width when horizontal is True) of the divider between the controls, in pixels.When divider_thickness is 0, this creates empty space. When divider_thickness is greater than 0, this determines the divider height.

item_extent

item_extent
Number
default:"None"
A fixed height or width (when horizontal is True) of an item to optimize rendering.When all items have the same size, setting this property improves scrolling performance significantly.
This property has effect only when build_controls_on_demand is True or spacing is 0.

first_item_prototype

first_item_prototype
bool
default:"False"
Whether the dimensions of the first item of controls should be used as a “prototype” for all other items.When True, all items will have the same height (or width if horizontal) as the first item, which can improve performance.

prototype_item

prototype_item
Control
default:"None"
A control to be used as a “prototype” for all items. All items will have the same height (or width if horizontal) as the prototype.
This property has effect only when build_controls_on_demand is True or spacing is 0.

divider_thickness

divider_thickness
Number
default:"0"
If greater than 0, a Divider is used as spacing between list view items.The thickness of the divider line. The spacing property determines the total height allocated for the divider.

padding

padding
PaddingValue
default:"None"
The amount of space by which to inset the children.Can be a single number for uniform padding, or use ft.padding.all(), ft.padding.symmetric(), or ft.padding.only() for more control.

clip_behavior

clip_behavior
ClipBehavior
default:"ClipBehavior.HARD_EDGE"
How to clip the controls.Options:
  • ClipBehavior.HARD_EDGE - Clip with hard edges
  • ClipBehavior.ANTI_ALIAS - Clip with anti-aliasing
  • ClipBehavior.ANTI_ALIAS_WITH_SAVE_LAYER - Clip with anti-aliasing and save layer
  • ClipBehavior.NONE - No clipping

semantic_child_count

semantic_child_count
int
default:"None"
The number of children that will contribute semantic information for accessibility.Useful when the actual number of children is different from the semantic count.

cache_extent

cache_extent
Number
default:"None"
Items that fall in the cache area (before or after the visible area) are laid out even though they are not yet visible on screen.The cache_extent describes how many pixels the cache area extends before the leading edge and after the trailing edge of the viewport.The total extent covered is: cache_extent before + main axis extent + cache_extent after.A larger cache extent improves scrolling smoothness but uses more memory.

build_controls_on_demand

build_controls_on_demand
bool
default:"True"
Whether the controls should be built lazily/on-demand.When True (default), controls are only rendered when they’re about to become visible. This is particularly useful when dealing with a large number of controls and dramatically improves performance.

Layout Behavior

How Children Are Arranged

  1. Scroll Direction: Children are arranged linearly in the scroll direction (vertical by default, horizontal if horizontal is True).
  2. Cross Axis: Children fill the entire width (in vertical mode) or height (in horizontal mode).
  3. Spacing: The spacing property adds gaps between items.
  4. Lazy Rendering: When build_controls_on_demand is True, only visible items (plus cache area) are rendered.

Scrolling

ListView inherits from ScrollableControl and is scrollable by default. You can control scrolling behavior:
ft.ListView(
    scroll=ft.ScrollMode.ADAPTIVE,  # or AUTO, ALWAYS, HIDDEN
    auto_scroll=True,
    controls=[...],
)

Examples

Basic Vertical List

ft.ListView(
    height=400,
    spacing=10,
    padding=20,
    controls=[
        ft.ListTile(
            leading=ft.Icon(ft.Icons.PERSON),
            title=ft.Text(f"User {i}"),
            subtitle=ft.Text(f"user{i}@example.com"),
        )
        for i in range(1, 21)
    ],
)

Horizontal Scrolling List

ft.ListView(
    horizontal=True,
    spacing=10,
    height=150,
    controls=[
        ft.Container(
            width=150,
            height=150,
            bgcolor=ft.Colors.AMBER,
            border_radius=10,
            alignment=ft.alignment.center,
            content=ft.Text(f"Card {i}", size=20),
        )
        for i in range(1, 11)
    ],
)

List with Dividers

ft.ListView(
    height=400,
    spacing=1,
    divider_thickness=1,
    controls=[
        ft.ListTile(
            title=ft.Text(f"Item {i}"),
            trailing=ft.Icon(ft.Icons.ARROW_FORWARD),
        )
        for i in range(1, 11)
    ],
)

Large List with Fixed Item Height

ft.ListView(
    height=600,
    item_extent=50,  # Each item is 50px tall
    build_controls_on_demand=True,
    controls=[
        ft.Container(
            height=50,
            content=ft.Text(f"Item {i}"),
            border=ft.border.all(1, ft.Colors.GREY),
        )
        for i in range(1, 1001)  # 1000 items!
    ],
)

List with Padding

ft.ListView(
    height=400,
    padding=ft.padding.symmetric(horizontal=20, vertical=10),
    spacing=5,
    controls=[
        ft.ElevatedButton(f"Button {i}")
        for i in range(1, 21)
    ],
)

Reverse Order List

ft.ListView(
    height=300,
    reverse=True,  # Scrolls from bottom to top
    controls=[
        ft.Text(f"Message {i}")
        for i in range(1, 21)
    ],
)

Chat-Style List

ft.ListView(
    height=500,
    spacing=8,
    padding=10,
    reverse=True,  # New messages at bottom
    auto_scroll=True,
    controls=[
        ft.Container(
            content=ft.Text(f"Message {i}"),
            bgcolor=ft.Colors.BLUE_100,
            border_radius=10,
            padding=10,
            alignment=ft.alignment.center_left,
        )
        for i in range(1, 51)
    ],
)

Performance Optimization

For Large Lists

When working with thousands of items:
  1. Enable lazy rendering: Keep build_controls_on_demand=True (default)
  2. Set fixed item size: Use item_extent or first_item_prototype
  3. Adjust cache extent: Use smaller values to reduce memory usage
ft.ListView(
    height=600,
    item_extent=60,  # Fixed height
    cache_extent=100,  # Small cache
    build_controls_on_demand=True,
    controls=[...],  # Thousands of items
)

Use Cases

  1. Contact Lists: Display user contacts with avatars and details
  2. Chat Messages: Show conversation history
  3. News Feeds: Display articles or posts
  4. Settings Menus: Create scrollable settings pages
  5. Product Catalogs: Show products in a list
  6. Horizontal Galleries: Create horizontal image galleries
  • GridView - 2D grid layout
  • Column - Non-scrollable vertical layout
  • Row - Non-scrollable horizontal layout
  • Stack - Overlapping layout

Build docs developers (and LLMs) love