Flutter Navigation Basics

Moving between screens in your app

🧭 What is Navigation?

Navigation in Flutter allows users to move between different screens or pages in your app. Using Navigator, you can push new screens onto a stack and pop them off, creating smooth transitions and intuitive user flows.


// Simple navigation example
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SecondPage()),
);
                                    

Output:

First Page
Second Page

Key Navigation Concepts

➡️

Push

Navigate to a new screen

Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => Page()),
)
⬅️

Pop

Go back to previous screen

Navigator.pop(context);
📦

Pass Data

Send data between screens

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => Page(data: 'Hello'),
  ),
)
↩️

Return Data

Get data from popped screen

final result = await Navigator.push(...);

🔹 Basic Navigation - Push

Navigate to a new screen using Navigator.push:

import 'package:flutter/material.dart';

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('First Page')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondPage()),
            );
          },
          child: Text('Go to Second Page'),
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Page')),
      body: Center(
        child: Text('Welcome to Second Page!'),
      ),
    );
  }
}

Output:

First Page

🔹 Going Back - Pop

Return to the previous screen using Navigator.pop:

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Page')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go Back'),
        ),
      ),
    );
  }
}

Output:

Second Page

🔹 Passing Data Forward

Send data to the next screen through constructor:

class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => SecondPage(
                  message: 'Hello from First Page!',
                ),
              ),
            );
          },
          child: Text('Send Data'),
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  final String message;
  
  SecondPage({required this.message});
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Page')),
      body: Center(
        child: Text(message),
      ),
    );
  }
}

Output (Second Page):

Second Page
Hello from First Page!

🔹 Returning Data Back

Get data back from a popped screen:

// First Page - Receiving data
class FirstPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            final result = await Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondPage()),
            );
            
            print('Received: $result');
          },
          child: Text('Get Data from Second Page'),
        ),
      ),
    );
  }
}

// Second Page - Sending data back
class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context, 'Data from Second Page');
          },
          child: Text('Send Data Back'),
        ),
      ),
    );
  }
}

Output:

Second Page
Returns: "Data from Second Page"

🔹 Navigation with Animation

Add custom transitions between screens:

Navigator.push(
  context,
  PageRouteBuilder(
    pageBuilder: (context, animation, secondaryAnimation) => SecondPage(),
    transitionsBuilder: (context, animation, secondaryAnimation, child) {
      const begin = Offset(1.0, 0.0);
      const end = Offset.zero;
      const curve = Curves.easeInOut;
      
      var tween = Tween(begin: begin, end: end).chain(
        CurveTween(curve: curve),
      );
      
      return SlideTransition(
        position: animation.drive(tween),
        child: child,
      );
    },
  ),
);

Output:

Slide transition from right →
Second Page

🔹 Replace Current Screen

Replace the current screen instead of stacking:

Navigator.pushReplacement(
  context,
  MaterialPageRoute(builder: (context) => NewPage()),
);

// User cannot go back to previous screen
// Useful for login -> home transitions

Output:

Login Page
Home Page (No back button)

🧠 Test Your Knowledge

Which method is used to go back to the previous screen?