Skip to content

Lezione 6: Navigazione — App multi-screen

  • Capire come funziona la navigazione in Flet
  • Creare app con più schermate
  • Passare dati tra una schermata e l’altra
  • Usare NavigationBar e NavigationDrawer

Le route (percorsi) permettono di avere più “pagine” nella stessa app, come in un sito web.

/home → Schermata Home
/prodotti → Schermata Prodotti
/profilo → Schermata Profilo

In Flet, quando cambiamo route, la pagina si aggiorna mostrando contenuti diversi.


import flet as ft
def main(page: ft.Page):
page.title = "App Multi-Screen"
page.padding = 30
def naviga(destinazione):
page.go(destinazione)
# Funzione chiamata quando la route cambia
def route_change(route):
page.views.clear() # Pulisce le viste precedenti
if page.route == "/":
page.views.append(
ft.View(
route="/",
controls=[
ft.Text("Home", size=30, weight="bold"),
ft.ElevatedButton("Vai a Prodotti", on_click=lambda _: naviga("/prodotti")),
ft.ElevatedButton("Vai a Contatti", on_click=lambda _: naviga("/contatti")),
]
)
)
elif page.route == "/prodotti":
page.views.append(
ft.View(
route="/prodotti",
controls=[
ft.Text("Prodotti", size=30, weight="bold"),
ft.Text("Elenco dei nostri prodotti..."),
ft.ElevatedButton("← Indietro", on_click=lambda _: naviga("/")),
]
)
)
elif page.route == "/contatti":
page.views.append(
ft.View(
route="/contatti",
controls=[
ft.Text("Contatti", size=30, weight="bold"),
ft.Text("Scrivici a info@esempio.com"),
ft.ElevatedButton("← Indietro", on_click=lambda _: naviga("/")),
]
)
)
page.update()
page.on_route_change = route_change
page.go("/") # Route iniziale
ft.app(target=main)

ft.View rappresenta una schermata completa. Proprietà principali:

ProprietàDescrizione
routeIl nome della route (es. "/home")
controlsLista dei componenti nella schermata
appbarBarra superiore (opzionale)
navigation_barBarra di navigazione inferiore (opzionale)
horizontal_alignmentAllineamento orizzontale
scrollScroll della schermata
bgcolorColore di sfondo
paddingSpazio dai bordi
page.views.append(
ft.View(
route="/dettaglio",
controls=[
ft.Text("Dettaglio Prodotto", size=28, weight="bold"),
ft.Text("Qui vedrai i dettagli..."),
ft.ElevatedButton("← Torna indietro", on_click=lambda _: page.go("/")),
]
)
)

ft.AppBar aggiunge una barra in cima alla schermata:

ft.View(
route="/",
appbar=ft.AppBar(
title=ft.Text("Home"),
bgcolor="blue",
color="white",
leading=ft.Icon(ft.icons.HOME), # Icona a sinistra
actions=[ # Azioni a destra
ft.IconButton(ft.icons.SETTINGS, on_click=lambda _: print("Settings")),
ft.IconButton(ft.icons.NOTIFICATIONS, on_click=lambda _: print("Notifiche")),
],
),
controls=[
ft.Text("Contenuto della Home", size=20),
]
)
ProprietàDescrizione
titleTitolo centrale (ft.Text)
bgcolorColore sfondo
colorColore testo/icone
leadingWidget a sinistra (es. icona menu)
actionsLista di widget a destra
center_titleCentra il titolo (True/False)

5. Esempio guidato: App con navigazione completa

Section titled “5. Esempio guidato: App con navigazione completa”
import flet as ft
def main(page: ft.Page):
page.title = "My App"
page.theme_mode = ft.ThemeMode.LIGHT
def naviga(e, destinazione):
page.go(destinazione)
def route_change(route):
page.views.clear()
# === HOME ===
if page.route == "/":
page.views.append(
ft.View(
route="/",
appbar=ft.AppBar(
title=ft.Text("Home"),
bgcolor=ft.colors.BLUE,
color=ft.colors.WHITE,
center_title=True,
),
controls=[
ft.Container(
content=ft.Column([
ft.Text("🏠 Benvenuto!", size=32, weight="bold"),
ft.Text("Questa è la schermata principale.", size=16, color="grey"),
ft.Divider(height=30),
ft.ElevatedButton("📦 Vedi Prodotti", on_click=lambda e: naviga(e, "/prodotti"), width=250),
ft.ElevatedButton("📞 Contatti", on_click=lambda e: naviga(e, "/contatti"), width=250),
ft.ElevatedButton("ℹ️ Info App", on_click=lambda e: naviga(e, "/info"), width=250),
], alignment=ft.MainAxisAlignment.CENTER),
padding=30,
)
],
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
)
)
# === PRODOTTI ===
elif page.route == "/prodotti":
page.views.append(
ft.View(
route="/prodotti",
appbar=ft.AppBar(
title=ft.Text("Prodotti"),
bgcolor=ft.colors.BLUE,
color=ft.colors.WHITE,
leading=ft.IconButton(ft.icons.ARROW_BACK, on_click=lambda _: page.go("/")),
),
controls=[
ft.ListView(spacing=10, padding=20, expand=True, auto_scroll=False),
],
)
)
# Aggiunge prodotti alla lista
prodotti = ["Laptop", "Smartphone", "Tablet", "Cuffie", "Mouse"]
for p in prodotti:
page.views[-1].controls[0].controls.append(
ft.Container(
content=ft.Row([
ft.Icon(ft.icons.ELECTRONICS, color="blue"),
ft.Column([
ft.Text(p, weight="bold", size=16),
ft.Text("Prodotto disponibile", color="green", size=12),
]),
ft.Icon(ft.icons.CHEVRON_RIGHT, color="grey"),
]),
padding=15,
bgcolor="white",
border_radius=10,
shadow=ft.BoxShadow(blur_radius=5, color=ft.colors.GREY_300),
)
)
# === CONTATTI ===
elif page.route == "/contatti":
page.views.append(
ft.View(
route="/contatti",
appbar=ft.AppBar(
title=ft.Text("Contatti"),
bgcolor=ft.colors.BLUE,
color=ft.colors.WHITE,
leading=ft.IconButton(ft.icons.ARROW_BACK, on_click=lambda _: page.go("/")),
),
controls=[
ft.Column([
ft.ListTile(
leading=ft.Icon(ft.icons.EMAIL),
title=ft.Text("Email"),
subtitle=ft.Text("info@esempio.com"),
),
ft.ListTile(
leading=ft.Icon(ft.icons.PHONE),
title=ft.Text("Telefono"),
subtitle=ft.Text("+39 123 456 7890"),
),
ft.ListTile(
leading=ft.Icon(ft.icons.LOCATION_ON),
title=ft.Text("Indirizzo"),
subtitle=ft.Text("Via Roma 1, Milano"),
),
], spacing=5),
]
)
)
elif page.route == "/info":
page.views.append(
ft.View(
route="/info",
appbar=ft.AppBar(
title=ft.Text("Info App"),
bgcolor=ft.colors.BLUE,
color=ft.colors.WHITE,
leading=ft.IconButton(ft.icons.ARROW_BACK, on_click=lambda _: page.go("/")),
),
controls=[
ft.Column([
ft.Text("My App v1.0", size=24, weight="bold"),
ft.Text("Creata con Flet e Python", color="grey"),
ft.Text("Anno 2025-2026", color="grey"),
], alignment=ft.MainAxisAlignment.CENTER, horizontal_alignment=ft.CrossAxisAlignment.CENTER),
],
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
vertical_alignment=ft.MainAxisAlignment.CENTER,
)
)
page.update()
page.on_route_change = route_change
page.go("/")
ft.app(target=main)

Invece di ricostruire la view, possiamo usare page.views.pop() per tornare indietro:

def route_change(route):
# Se stiamo navigando all'indietro (già nella pila)
# non serve ricostruire
...
# Bottone Back che fa pop:
ft.IconButton(
ft.icons.ARROW_BACK,
on_click=lambda _: page.views.pop() or page.update()
)

ComandoDescrizione
page.go("/route")Naviga a una route
page.viewsPila delle viste (lista)
page.views.clear()Pulisce tutte le viste
page.views.append(ft.View(...))Aggiunge una nuova vista
page.views.pop()Torna alla vista precedente
page.on_route_changeFunzione chiamata al cambio route
page.routeRoute corrente
ft.View(route="/", controls=[...])Crea una nuova schermata
ft.AppBar(title=..., bgcolor=...)Barra superiore

Crea un file ricette.py che realizzi un’app di ricette con navigazione:

Schermata Home (/):

  • Titolo ”🍳 Le Mie Ricette”
  • Griglia (GridView) con almeno 4 ricette (usa nomi e icone)
  • Ogni card è cliccabile → naviga alla schermata dettaglio

Schermata Dettaglio (/ricetta/1, /ricetta/2, …):

  • Mostra il nome della ricetta (grande, grassetto)
  • Mostra ingredienti (usa una lista con bullet)
  • Mostra procedimento (paragrafo)
  • Un bottone ”← Torna alle ricette”

Requisiti tecnici:

  • Usa ft.View per ogni schermata
  • Usa ft.AppBar con titolo e back button
  • Usa page.on_route_change per gestire la navigazione
  • Le card sulla home devono avere ombra e angoli arrotondati
  • Per passare l’ID ricetta: usa route tipo "/ricetta/1" e poi analizza page.route con .split("/")
  • Per le card cliccabili: usa ft.Container(on_click=...) o avvolgi in ft.GestureDetector
  • Usa ft.ListTile per un layout pulito degli ingredienti