Navigator in Flutter: aprire e chiudere schermate con push e pop

Foto di Clay Banks su Unsplash

GuidePrincipiante25 min Flutter 3.x

Navigator in Flutter: aprire e chiudere schermate con push e pop

La navigazione è uno dei primi concetti che serve padroneggiare quando si costruisce un'app Flutter: quasi ogni applicazione ha più di una schermata.

In Flutter le schermate si chiamano route e vengono gestite da un widget chiamato Navigator, che funziona come una pila (stack): push mette una nuova schermata in cima, pop la toglie tornando a quella precedente.

In questo tutorial per principianti costruiremo una piccola app con due schermate: una Home con un pulsante e una schermata di dettaglio. Vedremo MaterialPageRoute, le rotte nominate e come personalizzare il tasto indietro.

  1. 1

    Creare il progetto e la struttura di base

    Crea un nuovo progetto e apri lib/main.dart. Partiamo da una MaterialApp con una semplice schermata Home.

    Il widget MaterialApp crea automaticamente un Navigator interno: non dobbiamo configurarlo a mano.

    import 'package:flutter/material.dart';
    
    void main() => runApp(const MyApp());
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Demo Navigator',
          theme: ThemeData(colorSchemeSeed: Colors.indigo),
          home: const HomePage(),
        );
      }
    }
    
    class HomePage extends StatelessWidget {
      const HomePage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: const Text('Home')),
          body: const Center(child: Text('Prima schermata')),
        );
      }
    }

    Risultato atteso

    L'app si avvia mostrando una AppBar con titolo "Home" e il testo "Prima schermata".

  2. 2

    Creare la seconda schermata

    Aggiungiamo una seconda schermata, DettaglioPage. È un normale StatelessWidget con il suo Scaffold: in Flutter una schermata non è nulla di speciale, è solo un widget.

    Puoi scriverla in fondo a main.dart oppure, meglio, in un file separato lib/dettaglio_page.dart.

    class DettaglioPage extends StatelessWidget {
      const DettaglioPage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(title: const Text('Dettaglio')),
          body: const Center(
            child: Text('Seconda schermata'),
          ),
        );
      }
    }

    Risultato atteso

    Il codice compila senza errori. La schermata non è ancora raggiungibile.

  3. 3

    Aprire la schermata con Navigator.push

    Ora colleghiamo le due schermate. Nel body della Home mettiamo un ElevatedButton che chiama Navigator.push.

    MaterialPageRoute descrive la rotta e fornisce l'animazione di transizione tipica della piattaforma. Il parametro builder riceve il BuildContext e restituisce il widget da mostrare.

    body: Center(
      child: ElevatedButton(
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => const DettaglioPage(),
            ),
          );
        },
        child: const Text('Vai al dettaglio'),
      ),
    ),

    Risultato atteso

    Toccando il pulsante si apre la schermata Dettaglio con un'animazione di scorrimento; la AppBar mostra automaticamente la freccia indietro.

  4. 4

    Tornare indietro con Navigator.pop

    La freccia indietro nella AppBar chiama già Navigator.pop per noi. Possiamo però tornare indietro anche da un pulsante nel corpo della pagina.

    Navigator.pop(context) rimuove la rotta in cima alla pila: attenzione a non chiamarlo sulla prima schermata, perché svuoterebbe lo stack.

    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Text('Seconda schermata'),
          const SizedBox(height: 16),
          OutlinedButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('Torna indietro'),
          ),
        ],
      ),
    ),

    Risultato atteso

    Dal Dettaglio, il pulsante "Torna indietro" riporta alla Home esattamente come la freccia della AppBar.

  5. 5

    Usare le rotte nominate

    Quando le schermate aumentano, conviene dichiarare le rotte in un unico punto con routes e aprirle con Navigator.pushNamed.

    Con initialRoute indichiamo quale rotta mostrare all'avvio (al posto di home).

    MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => const HomePage(),
        '/dettaglio': (context) => const DettaglioPage(),
      },
    );
    
    // Nella HomePage:
    ElevatedButton(
      onPressed: () => Navigator.pushNamed(context, '/dettaglio'),
      child: const Text('Vai al dettaglio'),
    );

    Risultato atteso

    La navigazione funziona come prima, ma i percorsi sono centralizzati e più leggibili.

  6. 6

    Personalizzare il tasto indietro

    Puoi sostituire la freccia automatica con un widget tuo usando leading nella AppBar. È utile, ad esempio, per chiedere conferma prima di uscire.

    Un metodo comodo è Navigator.maybePop(context): esegue il pop solo se è possibile, evitando errori.

    appBar: AppBar(
      title: const Text('Dettaglio'),
      leading: IconButton(
        icon: const Icon(Icons.close),
        tooltip: 'Chiudi',
        onPressed: () => Navigator.maybePop(context),
      ),
    ),

    Risultato atteso

    La AppBar del Dettaglio mostra una X al posto della freccia; premendola si torna alla Home.

  7. 7

    Verificare lo stack e ricapitolare

    Per capire se ci sono rotte sotto quella corrente usa Navigator.canPop(context): restituisce false sulla prima schermata.

    Ricapitolando:

    • Navigator.push → apre una nuova schermata
    • Navigator.pop → chiude quella corrente
    • MaterialPageRoute → definisce la rotta e l'animazione
    • routes + pushNamed → rotte nominate centralizzate

    Prossimo passo: passare dati tra le schermate tramite il costruttore e ricevere un risultato da pop.

    if (Navigator.canPop(context)) {
      Navigator.pop(context);
    } else {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Sei già nella prima schermata')),
      );
    }

    Risultato atteso

    L'app naviga correttamente avanti e indietro senza errori in console.

CondividiXLinkedInFacebookWhatsApp

Commenti (0)

Ancora nessun commento. Inizia tu!