Flutter Navigation – The Basics

This is the first article of a multi-part series where we will focus on how to navigate within a Flutter app.  In this article, we are going to cover the basics of navigating between screens in Flutter.  In future articles we’ll cover more advanced topics like building menus, named routes, and how to prevent navigation.  Preventing navigation is useful if you want to limit access to a specific page or if you want to keep a user on a specific page until their intended task is complete.

If you are interested in reading this entire series, here are the links for you:

The Basics of Navigation

When dealing with navigation in Flutter, you’ll become very familiar with two classes: Navigator and Route.  Navigator allows you to move between screens (aka pages).  Route is simply an abstraction of a screen used by Navigator.  So if I build two screens – lets call these screen1 and screen2, Navigator considers the screens as Routes and I can move between screen1 and screen2 using Navigator.  And just in case it is not clear these screens are just widgets that you build.  We’ll show you how to build those widgets and navigate between them!

Creating the App

If you are not yet familiar with the basics of creating a flutter app, please see my first post in this series on flutter – From Zero to App with Flutter.

Note – for this post we’ll be using VS Code although other IDEs may be used.  Open up VS Code and from the command palette (CTRL+SHIFT+P) choose ‘Flutter:New Project’.  Enter a new project name and hit Enter.  VS Code will setup your new project, which we will be heavily modifying next…

The structure of this app will be comprised of 3 files –

Our main.dart file is rather straight forward.  All we are doing inside main.dart is setting up the Flutter app.  Open up your main.dart file and replace its entire contents with the following code:

import 'package:flutter/material.dart';
import 'home.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Nav Demo 1',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(),
    );
  }
}

What the above code does is setup a Flutter App and tell the Flutter framework to display by default an instance of MyHomePage.  Let’s go ahead and create the home page by adding a new file named home.dart and place within it the following code:

import 'package:flutter/material.dart';
import 'about.dart';

class MyHomePage extends StatefulWidget {
  
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

void _navAbout(BuildContext context) {
  Navigator.push(
      context, new MaterialPageRoute(builder: (context) => new AboutPage()));
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Home Page'),
      ),
      body: new Center(
        child: new RaisedButton(
          child: new Text('Visit About Page'),
          onPressed: () => _navAbout(context),
        ),
      ),
    );
  }
}

The code we placed within home.dart contains the definition and behavior of our first widget – our home page.  It’s pretty straight forward – it has a button in the center of the page that reads – ‘Visit About Page’.  It also defines an onPressed event handler so that when the button is pressed, the _navAbout method fires and it is within this method that we are first introduced to Navigator:

void _navAbout(BuildContext context) {
  Navigator.push(
      context, new MaterialPageRoute(builder: (context) => new AboutPage()));
}

Within _navAbout, we call Navigator.push in order to push a new instance of the AboutPage onto the navigation stack.  Yep, that is right, navigation within Flutter is a stack based navigation where you push new pages on the stack or pop off an existing page to essentially ‘go back’.

At this point your app will not yet run as it is missing one final piece.  Create another file and name it about.dart.  This file will contain the following source code that will define your about page:

import 'package:flutter/material.dart';

class AboutPage extends StatefulWidget {

  @override
  _AboutPageState createState() => new _AboutPageState();
}

void _navHome(BuildContext context) {
  Navigator.pop(context);
}

class _AboutPageState extends State<AboutPage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('About'),
      ),
      body: new Center(
        child: new RaisedButton(
          child: new Text('Back to Home Page'),
          onPressed: () => _navHome(context),
        ),
      ),
    );
  }
}

The AboutPage widget is similar to the home page widget in that it has a button you can click to navigate.  In this case we navigate to the home page – and since this is the page we just came from, a simple Navigator.pop will do.  Take note of the _navHome method and how we call Navigator.pop.

Summary

As you can see, navigation in Flutter uses easy to understand concepts like a Navigator and Route.  Navigation is based on a stack of Routes (aka pages or screens) that we push or pop to go where we intend.  This is of course a simplification of things and we will look at more complicated scenarios in future articles.

If you would like to, you can grab the source code for this demo app here: https://github.com/jebright/flutter_nav_app

3 thoughts on “Flutter Navigation – The Basics”

Leave a Reply

Your email address will not be published. Required fields are marked *