Nella lezione precedente abbiamo preso familiarità con i componenti Route
, Navigator
e MaterialRoutePage
che sono fondamentali per definire la navigazione e il routing di un applicazione Flutter.
In questa e nella prossima lezione vedremo i principali approcci da utilizzare per introdurre la navigazione e il routing nella propria applicazione e per gestire eventuali errori che possono accadere durante la navigazione.
Utilizzo del widget Navigator tramite i metodi push e pop
Creiamo un nuovo progetto come illustrato nella lezione 6 di questa guida e cancelliamo tutto eccetto la classe MyApp
, definita come segue.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: /*insert home*/
);
}
}
Definiamo inoltre due schermate per la nostra applicazione che chiameremo HomePage
e NewPage
, definite come segue.
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('HomePage'),
),
body: Center(
child: RaisedButton(
child: Text('Go to the NewPage'),
),
),
);
}
}
class NewPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("NewPage"),
),
body: Center(
child: RaisedButton(
child: Text('Go back!'),
),
),
);
}
}
Entrambe le classi definiscono un RaisedButton
posto al centro della schermata, che permetterà di navigare dalla HomePage
alla NewPage
e viceversa.
Definito lo scheletro della nostra applicazione, possiamo iniziare da un esempio di navigazione molto semplice che faccia uso dei metodi Navigator.push
e Navigator.pop
per muoverci rispettivamente tra le due schermate appena definite.
Per fare ciò, aggiungiamo al RaisedButton
definito nella schermata HomePage
la proprietà onPressed
, come segue:
onPressed: () {
Route route = MaterialPageRoute(builder: (context) => NewPage());
Navigator.push(context, route);
},
In questo modo, l'utente potrà spostarsi dalla HomePage
alla schermata NewPage
attraverso il metodo Navigator.push
. In questo caso la funzione prenderà in input il BuildContext
e la Route
creata tramite il costruttore della classe MaterialPageRoute
.
Facendo uso del widget MaterialPageRoute
, la schermata corrente di HomePage
verrà sostituita da una transizione, dipendente dalla piattaforma su cui è installata l'applicazione, per mostrare la nuova schermata NewPage
.
Una volta atterrato su questa pagina, l'utente potrà compiere un'unica operazione, ossia cliccare sul RaisedButton
presente al centro della schermata. Definiamo quindi la proprietà onPressed
di questo secondo bottone in modo da invocare il metodo Navigator.pop
per tornare alla schermata precedente.
onPressed: () {
Navigator.pop(context);
},
Impostiamo, infine, la proprietà home della classe MaterialApp
al valore
home: HomePage(),
ed eseguiamo l'applicazione per vedere il risultato della navigazione.
Come si può notare in figura, quando si trova nella schermata NewPage
, l'utente ha la possibilità di tornare alla schermata precedente tramite il RaisedButton
definito con il metodo Navigator.pop
, e attraverso la back arrow presente nell'AppBar
e definita in automatico dal framework quando non è la prima rotta nello stack, ossia quando Route.isFirst
è false
.
Questo è tra tutti il metodo più semplice in assoluto per inserire la navigazione tra due pagine dell'applicazione. Cionostante, per applicazioni articolate composte da più pagine, è sconsigliato utilizzare questo approccio.
Utilizzo delle rotte nominali
Un approccio più robusto è offerto dalle rotte nominali definite tramite la proprietà routes di MaterialApp
. Per implementare la navigazione tra le schermate HomePage
e NewPage
dovremo:
- utilizzare la proprietà route di
MaterialApp
; - definire un dizionario dove la chiave corrisponde al nome della rotta, mentre il valore è a tutti gli effetti una funzione di
build
, che creerà la rotta di interesse e mostrerà il widget associato a essa.
Modifichiamo la classe MyApp
al fine di aggiungere la proprietà route
.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
routes: mainRouting(),
);
}
Map<String, WidgetBuilder> mainRouting(){
return {
'/': (context) => HomePage(),
'/newpage': (context) => NewPage(),
};
}
}
Per semplicità, abbiamo definito il metodo mainRouting
all'interno della classe MyApp
per la definizione delle rotte.
Di default il framework, in assenza della definizione della proprietà MaterialApp.home
, andrà a cercare tra le rotte disponibili quella con nome uguale a /
per identificare la prima schermata. Se questa non dovesse essere definita, verrà visualizzato un errore.
A questo punto basterà sostituire il metodo RaisedButton.onPressed
definito nel widget HomePage
come segue.
onPressed: () {
Navigator.pushNamed(context, '/newpage');
},
In questo caso avendo definito le rotte di navigazione, abbiamo usato il metodo Navigator.pushNamed
che prende in input:
- il
BuildContext
; - il nome della rotta, che deve combaciare con una di quelle definite nella proprietà route di
MaterialApp
, altrimenti l'applicazione andrà in errore.
Eseguiamo l'applicazione così modificata per ottenere il seguente risultato.
Il risultato ottenuto è inalterato rispetto alla figura precedente, ma ci permette di avere una gestione della navigazione diversa e più robusta.
Il codice di questa lezione è disponibile su GitHub.