Navigator & Routes
The route stack
Section titled “The route stack”Navigator is a widget that manages a stack of routes. A route is a screen. The route on top of the stack is what the user sees. Navigation is just two stack operations: push a new route on top, or pop the top route off to reveal the one beneath.
flowchart TB
subgraph stack["route stack"]
top["DetailScreen (visible, top)"]
mid["ListScreen"]
bottom["HomeScreen (bottom)"]
end
top -->|pop| mid
mid -->|push DetailScreen| top The hardware/software back button, the app-bar back arrow, and a swipe-back gesture all do the same thing: pop the top route.
push and pop
Section titled “push and pop”You get the Navigator from the current BuildContext with Navigator.of(context), then push a route. A MaterialPageRoute gives you the platform-correct transition animation for free.
// Push a new screen onto the stack.Navigator.of(context).push( MaterialPageRoute(builder: (context) => const DetailScreen()),);
// Pop back to the previous screen.Navigator.of(context).pop();The builder is a function that returns the screen widget — it runs when the route is created, not when you call push.
Passing data forward
Section titled “Passing data forward”The cleanest way to send data to the next screen is a plain constructor argument. No magic, no global state — just pass it in.
Navigator.of(context).push( MaterialPageRoute( builder: (context) => DetailScreen(userId: 42), ),);
// DetailScreen receives it like any widget:class DetailScreen extends StatelessWidget { const DetailScreen({super.key, required this.userId}); final int userId; // ...}Returning a result back
Section titled “Returning a result back”Navigator.push returns a Future that completes when the pushed route is popped — so you can await a result the user chose on the next screen (a selection, a confirmation).
// Caller awaits the result of the pushed screen.final picked = await Navigator.of(context).push<Color>( MaterialPageRoute(builder: (context) => const ColorPicker()),);if (picked != null) { // use the returned Color}
// Inside ColorPicker, return a value by passing it to pop:Navigator.of(context).pop(Colors.blue);Named routes
Section titled “Named routes”For a small app you can register named routes in MaterialApp and navigate by string name. It centralizes the route table, but note: named routes get clumsy with typed arguments and deep links, which is exactly why the ecosystem moved to declarative routing (next lesson).
MaterialApp( routes: { '/': (context) => const HomeScreen(), '/settings': (context) => const SettingsScreen(), },);
Navigator.of(context).pushNamed('/settings');