Dart Tutorial

Flutter Lesson 33 of 83 3 min read

Navigation in Flutter: Navigator.push and pop

Learn screen navigation in Flutter with Navigator.push, pop, pushReplacement and pushAndRemoveUntil, and how the navigation stack works.

On this page

Flutter keeps screens in a stack, like a pile of cards. Opening a screen pushes it on top. Going back pops it off, revealing the one beneath. A screen is called a route.

Push and pop #

import 'package:flutter/material.dart';

void main() => runApp(const MaterialApp(home: HomePage()));

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home')),
      body: Center(
        child: FilledButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute<void>(builder: (context) => const DetailsPage()),
            );
          },
          child: const Text('Open details'),
        ),
      ),
    );
  }
}

class DetailsPage extends StatelessWidget {
  const DetailsPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Details')),
      body: Center(
        child: OutlinedButton(
          onPressed: () => Navigator.pop(context),
          child: const Text('Go back'),
        ),
      ),
    );
  }
}
  • MaterialPageRoute wraps the new page and gives it the platform’s standard transition.
  • The AppBar on the second page shows a back arrow automatically.
  • The system back button and the iOS back swipe also pop the route.

The stack #

Start:            [Home]
push Details:     [Home, Details]
push Reviews:     [Home, Details, Reviews]
pop:              [Home, Details]
pop:              [Home]

Replacing instead of stacking #

Sometimes the user should not be able to go back, for example from a login screen once they are signed in.

// Replace the current screen.
Navigator.pushReplacement(
  context,
  MaterialPageRoute<void>(builder: (context) => const HomePage()),
);

// Clear the whole stack and start again from a new screen.
Navigator.pushAndRemoveUntil(
  context,
  MaterialPageRoute<void>(builder: (context) => const LoginPage()),
  (route) => false, // remove every existing route
);

// Pop back to the first screen.
Navigator.popUntil(context, (route) => route.isFirst);
MethodStack beforeStack after
push(C)A, BA, B, C
pop()A, B, CA, B
pushReplacement(C)A, BA, C
pushAndRemoveUntil(C, (r) => false)A, BC
popUntil((r) => r.isFirst)A, B, CA

Can we go back? #

if (Navigator.canPop(context)) {
  Navigator.pop(context);
}

Navigator.maybePop(context); // pops only if possible

Full-screen dialogs #

A page for creating something often slides up from the bottom and shows a close icon in place of a back arrow.

Navigator.push(
  context,
  MaterialPageRoute<void>(
    fullscreenDialog: true,
    builder: (context) => const NewNotePage(),
  ),
);

After an await, the screen may no longer exist. Check before you use context.

Future<void> _save() async {
  await repository.save(note);
  if (!mounted) return;      // in a State class
  Navigator.pop(context);
}

In a StatelessWidget or a helper function, check context.mounted.

Shorter calls #

Navigator.of(context).push(...) and Navigator.push(context, ...) are the same thing. Many teams add an extension:

extension NavigationX on BuildContext {
  Future<T?> push<T>(Widget page) =>
      Navigator.of(this).push<T>(MaterialPageRoute(builder: (_) => page));

  void pop<T>([T? result]) => Navigator.of(this).pop(result);
}

// Usage
context.push(const DetailsPage());

Is this enough? #

Navigator.push is all a small app needs. Once you want web URLs, deep links from notifications, or redirects based on login state, switch to a routing package. See go_router.

Try it yourself #

Build three screens: a list of fruit, a details screen for the fruit that was tapped, and a “thank you” screen reached from details. On the thank-you screen, add a button that returns straight to the list.

Practise in the playground Updated by Santosh Adhikari