Skip to main content

Implementing Basic Navigation

1. Using Navigator.push() Method

Property Description Example
context The BuildContext of the current widget BuildContext context
widget The widget to navigate to Widget widget

Example: Pushing a New Screen

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => SecondScreen(),
  ),
);
Note: The MaterialPageRoute is used for iOS and Android platforms.
Warning: Ensure that the context is valid and accessible within the scope where Navigator is called.

2. Using Navigator.pop() Method

Method Description Parameters Return Type
Navigator.pop() Removes the current screen from the navigation stack and returns to the previous screen. BuildContext context Future<bool>
Navigator.pop(context, result) Removes the current screen and returns a result to the previous screen. BuildContext context, Object? result Future<bool>

Example: Navigating Back with Result

class MyScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('My Screen')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context, 'Result from MyScreen');
          },
          child: Text('Go Back with Result'),
        ),
      ),
    );
  }
}

Example: Navigating Back Without Result

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Screen')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go Back'),
        ),
      ),
    );
  }
}
Note: The Navigator.pop() method is asynchronous and returns a Future. It's important to await it if you're performing actions after navigation.

3. Using MaterialPageRoute Widget

Property Values Description
builder WidgetBuilder Required. A function that builds the widget for the new screen.
fullscreenDialog bool Optional. If true, the route is a full-screen dialog.
maintainState bool Optional. If false, the route's widget is disposed when popped.
pageStorageBucket PageStorageBucket Optional. The bucket to use for page storage.
transitionDelegate TransitionDelegate Optional. Controls how the route transitions.
reverseTransitionDelegate TransitionDelegate Optional. Controls how the route transitions when popped.

Example: Navigating to a New Screen

onPressed: () {
  Navigator.push(
    context,
    MaterialPageRoute(
      builder: (context) => SecondScreen(),
    ),
  );
}

Example: Passing Data to the New Screen

onPressed: () {
  Navigator.push(
    context,
    MaterialPageRoute(
      builder: (context) => SecondScreen(
        title: 'Second Screen',
      ),
    ),
  );
}
Note: The MaterialPageRoute is the default route for Material Design apps in Flutter.

4. Using CupertinoPageRoute Widget

Property Values Description
builder WidgetBuilder Required. The widget builder for the route content.
fullscreenDialog bool Optional. Whether the route is a full-screen dialog.
maintainState bool Optional. Whether to keep the route's state when it is not visible.
name String Optional. The name of the route for debugging purposes.
settings RouteSettings Optional. Additional settings for the route.

Example: Navigating with CupertinoPageRoute

import 'package:flutter/cupertino.dart';

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        middle: Text('Home'),
      ),
      child: Center(
        child: CupertinoButton(
          onPressed: () {
            Navigator.push(
              context,
              CupertinoPageRoute(
                builder: (context) => SecondScreen(),
              ),
            );
          },
          child: Text('Go to Second Screen'),
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: CupertinoNavigationBar(
        middle: Text('Second Screen'),
      ),
      child: Center(
        child: Text('This is the second screen.'),
      ),
    );
  }
}
Note: CupertinoPageRoute is designed to match the iOS design language and provides a native look and feel for iOS users.

5. Passing Arguments to Routes

Property Description Example
arguments Passes a map of arguments to the route {'userId': '123', 'userName': 'JohnDoe'}
onGenerateRoute Used to define custom route handling logic
onGenerateRoute: (settings) {
  if (settings.name == '/user') {
    return MaterialPageRoute(
      builder: (context) => UserScreen(
        arguments: settings.arguments,
      ),
    );
  }
}

Example: Passing Arguments to a Route

Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => UserProfileScreen(
      arguments: {'userId': '123'},
    ),
  ),
);

Example: Accessing Passed Arguments

class UserProfileScreen extends StatelessWidget {
  final Map<String, dynamic> arguments;

  UserProfileScreen({required this.arguments});

  @override
  Widget build(BuildContext context) {
    final userId = arguments['userId'];
    return Scaffold(
      appBar: AppBar(title: Text('User Profile')),
      body: Center(child: Text('User ID: $userId')),
    );
  }
}

6. Receiving Data from Popped Routes

Property Description Usage
result Value returned when popping a route Navigator.pop(context, result);

Example: Receiving Data from Popped Route

class DataReceiver extends StatefulWidget {
  @override
  _DataReceiverState createState() => _DataReceiverState();
}

class _DataReceiverState extends State<DataReceiver> {
  String receivedData = "";

  Future<void> _navigateAndReceiveData() async {
    final result = await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => DataSender(),
      ),
    );

    if (result != null) {
      setState(() {
        receivedData = result;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Data Receiver")),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("Received: $receivedData"),
            ElevatedButton(
              onPressed: _navigateAndReceiveData,
              child: Text("Navigate to Sender"),
            ),
          ],
        ),
      ),
    );
  }
}

Example: Sending Data from Route

class DataSender extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Data Sender")),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.pop(context, "Hello from sender!");
          },
          child: Text("Send Data and Pop"),
        ),
      ),
    );
  }
}

7. Using Navigator.pushReplacement() Method

The Navigator.pushReplacement() method in Flutter is used to navigate to a new screen and replace the current screen in the navigation stack. This means that when the user presses the back button, they will not return to the previous screen but instead exit the app or navigate to a different screen.

Parameter Description Required
context The BuildContext of the current screen. Yes
page The new screen (Widget) to navigate to. Yes

Example: Using Navigator.pushReplacement()

Navigator.pushReplacement(
  context,
  MaterialPageRoute(
    builder: (context) => SecondScreen(),
  ),
);
Note: The pushReplacement method replaces the current screen in the stack, so it's useful for login flows or when you want to prevent users from returning to a previous screen.

8. Using Navigator.pushAndRemoveUntil() Method

The Navigator.pushAndRemoveUntil() method is used to navigate to a new screen and remove all previous screens from the stack until a certain condition is met. This is useful for scenarios like logging out and returning to the login screen.

Parameter Type Description
context BuildContext The build context of the current screen.
predicate RoutePredicate A function that determines which routes to keep in the stack.
route Route The new route to navigate to.

Example: Navigating to a Home Screen and Removing All Previous Screens

Navigator.pushAndRemoveUntil(
  context,
  MaterialPageRoute(builder: (context) => HomeScreen()),
  (route) => route.isFirst,
);
Note: The isFirst property is used to identify the first route in the stack, ensuring all previous routes are removed.

9. Using Navigator.popUntil() Method

The Navigator.popUntil() method is used to pop multiple screens from the navigation stack until a specific condition is met. It allows you to navigate back to a particular screen in the stack, rather than popping one screen at a time.

Parameter Type Description
navigator NavigatorState The navigator state instance to use for popping screens.
predicate bool Function(Route<Object> route) A function that determines whether to pop the current route. Returns true if the route should be popped.

Example: Pop until a specific route is reached

Navigator.popUntil(
  context,
  (route) => route.settings.name == '/home',
);
Note: The popUntil method is useful for navigating back to a specific screen in the stack, such as returning to the home screen after completing a multi-step process.

10. Handling Back Button

Property Description Usage
onBackPressed Callback function when the back button is pressed onBackPressed: () { ... }
canPop Indicates if the current route can be popped bool canPop = Navigator.canPop(context);

Example: Handling Back Button in Flutter

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Home")),
      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"),
        leading: BackButton(
          onPressed: () {
            // Custom back button behavior
            Navigator.of(context).pop();
          },
        ),
      ),
      body: Center(
        child: Text("This is the second page"),
      ),
    );
  }
}
Note: The BackButton widget can be customized to handle back button presses with custom logic.
Warning: Ensure that the onPressed callback in BackButton properly navigates or handles the back press to avoid unexpected behavior.

Was this article helpful?