Flutter: Introduction of Routing and navigation

Flutter makes it easy and fast to build beautiful mobile apps.

If you don’t know about Flutter.io I would like you to read following articles

  1. What’s Revolutionary about Flutter?
  2. Article Series from Flutter Doc

Now, I assume that you have IntelliJ IDE, Android SDK and Xcode configured and you are ready to jump start Flutter Routing and Navigation

There are two core concepts and classes for managing multiple screens

  1. Route: A Route is an abstraction for a “screen” or “page” of an app, and a Navigator is a widget that manages routes.
  2. Navigator: A Navigator can push and pop routes to help a user move from screen to screen.

Mobile apps typically display full-screen elements called “screens” or “pages”. In Flutter these elements are called routes and they’re managed by a Navigator widget. The navigator manages a stack of Route objects and provides methods for managing the stack, like Navigator.push and Navigator.pop.

Example: In this example, I will design 2 screens each screen will have one button in centre.

Here is code for Screen 1

class Screen1 extends StatelessWidget {

@override
Widget build(BuildContext context) {
return new Scaffold( // 1
appBar: new AppBar( //2
title: new Text("Screen 1"),

),
body: new Center( // 3
child: new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new RaisedButton(onPressed:(){ // 4
button1(context); // 5
} ,child: new Text("Go to Screen 2"),)
],
),
) ,
);
}
}
  1. Scaffold is widget which is used to create Material Design. Scaffold documentation and Sample.
  2. AppBar is widget which is used to draw Android’s ActionBar / Toolbar / AppBar. AppBar documentation and Sample.
  3. Center is widget that centers its child within itself.
  4. RaisedButton is material style button. onPress event I create anonymous function which call another function called “button1” with BuildContext.
  5. Call build1 function which is responsible to change screen.

Code for Screen 2

class Screen2 extends StatelessWidget {

@override
Widget build(BuildContext context) {

return new Scaffold(
appBar: new AppBar(
title: new Text("Screen 2"),

),
body: new Center(
child: new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new RaisedButton(onPressed:(){
button2(context);
} ,child: new Text("Back to Screen 1"),)
],
),
) ,
);

}
}

Screen 2 code is almost same. onPress event I call button2 function other then that It’s same code.

Main function

void main() { // 1
runApp( // 2
new MaterialApp( //3
home: new Screen1(), //4
routes: <String, WidgetBuilder> { //5
'/screen1': (BuildContext context) => new Screen1(), //6
'/screen2' : (BuildContext context) => new Screen2() //7
},
)
);
}
  1. Flutter application starts with “void main()” function like other languages.
  2. The runApp function takes the given Widget and makes it the root of the widget tree. In our case it’s MaterialApp but It can be any Widget.
  3. MaterialApp is top level widget which is based on WidgetApp. It will make sure about behaviour of application like animation, shadow, etc..
  4. Render screen1 as home of MaterialApp. You can load splash screen as Home or it can be any widget.
  5. Routes is another property which takes map (string and widgetbuilder). You can consider it as url of screen or name reference of screen. / is default home page. In our case we have defined /screen1 and /screen2 named navigator route.
  6. Bind ‘/screen1’ with Screen1 object
  7. Bind ‘/screen2’ with Screen2 object

Button Click

void button1(BuildContext context){
print("Button 1"); //1
Navigator.of(context).pushNamed('/screen2'); //2
}

void button2(BuildContext context){
print("Button 2"); //3
Navigator.of(context).pop(true);//4
}
  1. print log when button1 clicked
  2. push named function of Navigator class will help to display new screen. in our case ‘/screen2’ will display. Note ‘/screen2’ must be same as routes property.
  3. print log when button2 clicked
  4. Pop current screen and It will display screen in back. In our case It will display screen1

Full Source Code

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


class Screen1 extends StatelessWidget {

@override
Widget build(BuildContext context) {
return new Scaffold( // 1
appBar: new AppBar(
title: new Text("Screen 1"), // screen title

),
body: new Center(
child: new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new RaisedButton(onPressed:(){
button1(context);
} ,child: new Text("Go to Screen 2"),)
],
),
) ,
);
}
}


class Screen2 extends StatelessWidget {

@override
Widget build(BuildContext context) {

return new Scaffold(
appBar: new AppBar(
title: new Text("Screen 2"),

),
body: new Center(
child: new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new RaisedButton(onPressed:(){
button2(context);
} ,child: new Text("Back to Screen 1"),)
],
),
) ,
);

}
}


void main() {
runApp(
new MaterialApp(
home: new Screen1(),
routes: <String, WidgetBuilder> {
'/screen1': (BuildContext context) => new Screen1(),
'/screen2' : (BuildContext context) => new Screen2()
},
)
);
}

void button1(BuildContext context){
print("Button 1");
Navigator.of(context).pushNamed('/screen2');
}

void button2(BuildContext context){
print("Button 2");
Navigator.of(context).pop(true);
}

Official Document for Routing and navigation