Skip to main content

RefreshIndicator

Shows a Material pull-to-refresh indicator above scrollable content.

Pulling the content down from its top edge, far enough, calls on_refresh and shows a spinning progress indicator until that handler returns. Call show to refresh without a gesture.

Note

The pull is a touch gesture: on desktop and web, mouse drags and the mouse wheel don't start it. Offer another way to refresh there, such as a button that calls show.

Inherits: LayoutControl

Properties

  • bgcolor - The color of the circle behind the progress indicator.
  • color - The color of the progress indicator.
  • content - The scrollable content, such as a ListView, a GridView, or a Column with scroll set.
  • displacement - How far below the top of the content the indicator rests while refreshing.
  • edge_offset - How far below the top of the content the indicator starts appearing, for example to start below a header that overlaps the content.
  • elevation - The elevation of the circle behind the progress indicator, which casts its shadow.
  • handle_nested_scrolls - Whether to react to the scrolling of scrollable controls nested in other scrollable controls in the content, rather than only to the outermost scrollable one.
  • semantics_label - The label screen readers announce for the progress indicator.
  • semantics_value - The progress value screen readers announce for the progress indicator.
  • stroke_width - The width of the progress indicator's line.
  • trigger_mode - Where a pull gesture can start a refresh.

Events

  • on_refresh - Called when the user pulls the indicator far enough, or show is called.

Methods

Examples​

Pull to refresh​

Pull the list down from its top to load a new message. The indicator spins until the async on_refresh handler returns:

Sourceplay_arrowTry Online
import asyncio
from datetime import datetime

import flet as ft


def main(page: ft.Page):
async def handle_refresh(e: ft.Event[ft.RefreshIndicator]):
# The indicator spins until this handler returns.
await asyncio.sleep(1.5)
messages.controls.insert(
0,
ft.ListTile(
title=ft.Text(f"Message {len(messages.controls) + 1}"),
subtitle=ft.Text(f"Received at {datetime.now():%H:%M:%S}"),
),
)

page.add(
ft.SafeArea(
expand=True,
content=ft.RefreshIndicator(
expand=True,
on_refresh=handle_refresh,
content=(
messages := ft.ListView(
expand=True,
controls=[
ft.ListTile(title=ft.Text(f"Message {i}"))
for i in range(3, 0, -1)
],
)
),
),
)
)


if __name__ == "__main__":
ft.run(main)

Refresh from a button​

On desktop and web, where the pull gesture isn't available, call show(), for example from a button, to show the indicator and run on_refresh:

Sourceplay_arrowTry Online
import asyncio
import random

import flet as ft


def get_price_tiles() -> list[ft.Control]:
return [
ft.ListTile(
title=symbol,
trailing=ft.Text(f"{random.uniform(50, 500):.2f}"),
)
for symbol in ["AAPL", "GOOG", "MSFT", "AMZN"]
]


def main(page: ft.Page):
async def handle_refresh(e: ft.Event[ft.RefreshIndicator]):
await asyncio.sleep(1)
prices.controls = get_price_tiles()

async def refresh(e: ft.Event[ft.IconButton]):
# Pulling is a touch gesture; on desktop and web, refresh from a button.
await indicator.show()

page.appbar = ft.AppBar(
title="Prices",
actions=[
ft.IconButton(ft.Icons.REFRESH, tooltip="Refresh", on_click=refresh),
],
)
page.add(
ft.SafeArea(
expand=True,
content=(
indicator := ft.RefreshIndicator(
expand=True,
color=ft.Colors.WHITE,
bgcolor=ft.Colors.BLUE,
on_refresh=handle_refresh,
content=(prices := ft.ListView(controls=get_price_tiles())),
)
),
)
)


if __name__ == "__main__":
ft.run(main)

Properties​

bgcolorclass-attributeinstance-attribute​

bgcolor: ColorValue | None = None

The color of the circle behind the progress indicator.

Defaults to ProgressIndicatorTheme.refresh_bgcolor, or else to Theme.canvas_color.

colorclass-attributeinstance-attribute​

color: ColorValue | None = None

The color of the progress indicator.

Defaults to ColorScheme.primary.

contentinstance-attribute​

content: Control

The scrollable content, such as a ListView, a GridView, or a Column with scroll set.

The pull gesture is made on this content, so it must be scrollable, but it can be pulled even when it is too short to scroll, such as an empty list.

Raises:

  • ValueError - If it is not visible.

displacementclass-attributeinstance-attribute​

displacement: Number = 40.0

How far below the top of the content the indicator rests while refreshing.

edge_offsetclass-attributeinstance-attribute​

edge_offset: Number = 0.0

How far below the top of the content the indicator starts appearing, for example to start below a header that overlaps the content.

elevationclass-attributeinstance-attribute​

elevation: Number = 2.0

The elevation of the circle behind the progress indicator, which casts its shadow.

Raises:

  • ValueError - If it is not greater than or equal to 0.

handle_nested_scrollsclass-attributeinstance-attribute​

handle_nested_scrolls: bool = False

Whether to react to the scrolling of scrollable controls nested in other scrollable controls in the content, rather than only to the outermost scrollable one.

Turn it on when the scrolling that should pull the indicator happens in a nested scrollable, such as a ListView inside a Column with scroll set.

semantics_labelclass-attributeinstance-attribute​

semantics_label: str | None = None

The label screen readers announce for the progress indicator.

Defaults to the localized "Refresh" label of the app's locale.

semantics_valueclass-attributeinstance-attribute​

semantics_value: str | None = None

The progress value screen readers announce for the progress indicator.

stroke_widthclass-attributeinstance-attribute​

stroke_width: Number = 2.0

The width of the progress indicator's line.

trigger_modeclass-attributeinstance-attribute​

Where a pull gesture can start a refresh.

Events​

on_refreshclass-attributeinstance-attribute​

on_refresh: ControlEventHandler[RefreshIndicator] | None = (
    None
)

Called when the user pulls the indicator far enough, or show is called.

The progress indicator spins until this handler returns, so make it an async handler that awaits the refresh work.

Methods​

showasync​

show(at_top: bool=True)

Shows the indicator and calls on_refresh, as a pull would.

Parameters:

  • at_top (bool, default: True) - Whether to show the indicator at the top of the content, rather than at its bottom.