Routing

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, a route is just a widget.

Navigate using Navigator Object

This process involves the following steps:

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: 'Navigation Basics',
    home: FirstRoute(),
  ));
}

class FirstRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Route'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Open route'),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => SecondRoute()),
            );
          },
        ),
      ),
    );
  }
}

class SecondRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Route"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

In the above example, we have two routes. One that shows "Open Route" button and the other that shows "Go Back" route. Tapping the button on the first route navigates to the second route. Tapping the button on the second route returns to the first route.

To switch to a new route, use the Navigator.push() method. The push() method adds a Route to the stack of routes managed by the Navigator.

To close the second route and return to the first use Navigator.pop() method. The pop() method removes the current Route from the stack of routes managed by the navigator.

Navigate with named routes

In the previous lesson, you learned how to navigate to a new screen by creating a new route and pushing it to the Navigator. However, if you need to navigate to the same screen in many parts of your app, this approach can result in code duplication. The solution is to define a named route, and use the named route for navigation.

This process involves the following steps

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: 'Named Routes Demo',
    // Start the app with the "/" named route. In this case, the app starts
    // on the FirstScreen widget.
    initialRoute: '/',
    routes: {
      // When navigating to the "/" route, build the FirstScreen widget.
      '/': (context) => FirstScreen(),
      // When navigating to the "/second" route, build the SecondScreen widget.
      '/second': (context) => SecondScreen(),
    },
  ));
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Center(
        child: RaisedButton(
          child: Text('Launch screen'),
          onPressed: () {
            // Navigate to the second screen using a named route.
            Navigator.pushNamed(context, '/second');
          },
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Screen"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            // Navigate back to the first screen by popping the current route
            // off the stack.
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

The MaterialApp widget accepts routes parameter which allows us to define application routes. In our example, we have defined only two named routes.

routes: {
      '/': (context) => FirstScreen(),
      '/second': (context) => SecondScreen(),
},

Notice in the above example we have initialRoute property. This property is used to specify the default route that the application will start with.

When using initialRoute, don’t define a home property.

Now we are done with the routes definition. Next we will navigate to the specified route using Navigator.pushNamed(). The following code takes us to the specified route:

onPressed: () {
  Navigator.pushNamed(context, '/second');
}

So tapping on the "Launch screen" button of first route takes us to the route screen /second.

To navigate back to the first screen, use the Navigator.pop() function.

onPressed: () {
  Navigator.pop(context);
}