Flutter 3.41 is live! Check out theblog post!
Navigate to a new screen and back
How to navigate between routes.
Most apps contain several screens for displaying different types of information. For example, an app might have a screen that displays products. When the user taps the image of a product, a new screen displays details about the product.
In Flutter,screens andpages are calledroutes. The remainder of this recipe refers to routes.
In Android, a route is equivalent to anActivity. In iOS, a route is equivalent to aViewController. In Flutter, a route is just a widget.
This recipe uses theNavigator to navigate to a new route.
The next few sections show how to navigate between two routes, using these steps:
- Create two routes.
- Navigate to the second route using
Navigator.push(). - Return to the first route using
Navigator.pop().
1. Create two routes
#First, create two routes to work with. Since this is a basic example, each route contains only a single button. Tapping the button on the first route navigates to the second route. Tapping the button on the second route returns to the first route.
First, set up the visual structure:
classFirstRouteextendsStatelessWidget{constFirstRoute({super.key});@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:constText('First Route')),body:Center(child:ElevatedButton(child:constText('Open route'),onPressed:(){// Navigate to second route when tapped.},),),);}}classSecondRouteextendsStatelessWidget{constSecondRoute({super.key});@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:constText('Second Route')),body:Center(child:ElevatedButton(onPressed:(){// Navigate back to first route when tapped.},child:constText('Go back!'),),),);}}classFirstRouteextendsStatelessWidget{constFirstRoute({super.key});@overrideWidgetbuild(BuildContextcontext){returnCupertinoPageScaffold(navigationBar:constCupertinoNavigationBar(middle:Text('First Route')),child:Center(child:CupertinoButton(child:constText('Open route'),onPressed:(){// Navigate to second route when tapped.},),),);}}classSecondRouteextendsStatelessWidget{constSecondRoute({super.key});@overrideWidgetbuild(BuildContextcontext){returnCupertinoPageScaffold(navigationBar:constCupertinoNavigationBar(middle:Text('Second Route')),child:Center(child:CupertinoButton(onPressed:(){// Navigate back to first route when tapped.},child:constText('Go back!'),),),);}}2. Navigate to the second route using Navigator.push()
# To switch to a new route, use theNavigator.push() method. Thepush() method adds aRoute to the stack of routes managed by theNavigator. Where does theRoute come from? You can create your own, or use a platform-specific route such asMaterialPageRoute orCupertinoPageRoute. A platform-specific route is useful because it transitions to the new route using a platform-specific animation.
In thebuild() method of theFirstRoute widget, update theonPressed() callback:
// Within the `FirstRoute` widget:onPressed:(){Navigator.push(context,MaterialPageRoute<void>(builder:(context)=>constSecondRoute(),),);}// Within the `FirstRoute` widget:onPressed:(){Navigator.push(context,CupertinoPageRoute<void>(builder:(context)=>constSecondRoute(),),);}3. Return to the first route using Navigator.pop()
# How do you close the second route and return to the first? By using theNavigator.pop() method. Thepop() method removes the currentRoute from the stack of routes managed by theNavigator.
To implement a return to the original route, update theonPressed() callback in theSecondRoute widget:
// Within the SecondRoute widgetonPressed:(){Navigator.pop(context);}Interactive example
#import 'package:flutter/material.dart';void main() { runApp(const MaterialApp(title: 'Navigation Basics', home: FirstRoute()));}class FirstRoute extends StatelessWidget { const FirstRoute({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('First Route')), body: Center( child: ElevatedButton( child: const Text('Open route'), onPressed: () { Navigator.push( context, MaterialPageRoute<void>( builder: (context) => const SecondRoute(), ), ); }, ), ), ); }}class SecondRoute extends StatelessWidget { const SecondRoute({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Second Route')), body: Center( child: ElevatedButton( onPressed: () { Navigator.pop(context); }, child: const Text('Go back!'), ), ), ); }}import 'package:flutter/cupertino.dart';void main() { runApp(const CupertinoApp(title: 'Navigation Basics', home: FirstRoute()));}class FirstRoute extends StatelessWidget { const FirstRoute({super.key}); @override Widget build(BuildContext context) { return CupertinoPageScaffold( navigationBar: const CupertinoNavigationBar(middle: Text('First Route')), child: Center( child: CupertinoButton( child: const Text('Open route'), onPressed: () { Navigator.push( context, CupertinoPageRoute<void>( builder: (context) => const SecondRoute(), ), ); }, ), ), ); }}class SecondRoute extends StatelessWidget { const SecondRoute({super.key}); @override Widget build(BuildContext context) { return CupertinoPageScaffold( navigationBar: const CupertinoNavigationBar(middle: Text('Second Route')), child: Center( child: CupertinoButton( onPressed: () { Navigator.pop(context); }, child: const Text('Go back!'), ), ), ); }}Additional navigation methods
# The recipe in this topic shows you one way to navigate to a new screen and back to the previous scene, using thepush andpop methods in theNavigator class, but there are several otherNavigator static methods that you can use. Here are a few of them:
pushAndRemoveUntil: Adds a navigation route to the stack and then removes the most recent routes from the stack until a condition is met.pushReplacement: Replaces the current route on the top of the stack with a new one.replace: Replace a route on the stack with another route.replaceRouteBelow: Replace the route below a specific route on the stack.popUntil: Removes the most recent routes that were added to the stack of navigation routes until a condition is met.removeRoute: Remove a specific route from the stack.removeRouteBelow: Remove the route below a specific route on the stack.restorablePush: Restore a route that was removed from the stack.
Unless stated otherwise, the documentation on this site reflects Flutter 3.41.2. Page last updated on 2025-10-28.View source orreport an issue.