Navigation

Now that I have the first screen of the app it’s time to add the second screen and find out how Flutter navigation works. The new screen will show a list of quizes (or sets of questions). Tapping on a quiz will take a user to the list of questions (the screen I already have).

Flutter offers several ways to navigate.

Routes

In terms of Flutter, routes are screens and pages. Navigating to another route (showing another screen) is quite simple:

// in QuizListWidget
onPressed: () {
  Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => QuestionListWidget()),
  );
}

Getting back is also not that hard:

// in QuestionListWidget
onPressed: () {
  Navigator.pop(context);
}

While this approach is very easy to implement it does couple screens. And that is something I would like to avoid.

This can be achieved by navigating using named routes.

Named routes

The concept is simple: you register a name for route and when navigating you specify the name of the route instead of the screen class.

onPressed: () {
	Navigator.pushNamed(context, '/quiz');
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: '/',
      routes: {
        '/': (context) => MyHomePage(title: "Quizes"),
        '/quiz': (context) {
          return BlocProvider(
              bloc: QuestionListBloc(), child: QuestionListWidget());
        }
      },
    );
  }
}

Now instead of home widget I have to specify the initial route to be opened.

Passing the arguments

There is one thing missing: I need to pass some arguments to the screen of questions. Even with named routes it is easy:

class QuestionListScreenArguments {
  final String quizId;
  final String quizName;

  QuestionListScreenArguments(this.quizId, this.quizName);
}
class QuestionListWidget extends StatelessWidget {
  static const route = '/quiz';

  @override
  Widget build(BuildContext context) {
    final args = ModalRoute.of(context).settings.arguments
        as QuestionListScreenArguments;
	// ...
}
onPressed: () {
  Navigator.pushNamed(context, '/quiz', 
            arguments: QuestionListScreenArguments(_quiz.id, _quiz.name));
}

Useful links: