• start by creating simple app with just one route
void main() => runApp(NavigationExampleApp());

class NavigationExampleApp extends StatelessWidget{

  @override
  Widget build(BuildContext context) => MaterialApp(
    title: "Navigation Example",
    home: FirstRoute(),
  );
}


class FirstRoute extends StatelessWidget{
  @override
  Widget build(BuildContext context) => Scaffold(
    body: Text("hello"),
  );

}
  • Use Navigator to move to the second page
RaisedButton(child: Text("to page 2"),onPressed: moveToSecondPage(context),)

  final moveToSecondPage = (BuildContext ctx) =>  
      () => 
          Navigator.push(ctx, MaterialPageRoute(builder:(ctx) => SecondRoute()));
  • add return button on page 2
 RaisedButton(
              child: Text("back to A"),
              onPressed: () => Navigator.pop(context),
            )

Passing parameters

  • pass parameters through constructor
//a parameter
class Message{
  final String title;
  final String content;

  Message(this.title, this.content);
}
class SecondRoute extends StatelessWidget {


  final Message _message;

  const SecondRoute(this._message);

  @override
  Widget build(BuildContext context) => Scaffold(
        body: Center(child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(_message.title, style: TextStyle(fontWeight: FontWeight.bold),),
            Text(_message.content),
  (...)
 RaisedButton(
                child: Text("to page 2"),
                onPressed: moveToSecondPage(context, Message("Message1", "Message1 Body")),
              )

Testing Navigation

First of all it is convenient to add unique key to a widget we want to easily find in tests - in our case the button which navigates to second page

  static const navigateToPage2Key = Key("gotoPage2");

   RaisedButton(
                key: navigateToPage2Key,
                child: Text("to page 2"),
                onPressed: moveToSecondPage(context, Message("Message1", "Message1 Body")),
              )

Then we can write a widget test which is available thanks to flutter-test library

 //https://api.flutter.dev/flutter/flutter_test/WidgetTester-class.html
  testWidgets("navigation", (WidgetTester tester) async {

  //We need to pump either whole application or 
   await tester.pumpWidget(NavigationExampleApp());

 //this is why a key assigned to a widget is very convenient
   final buttonToPage2=find.byKey(Key("gotoPage2"));

// "tap" actually represents pressing a button 
   final pressingButton=tester.tap(buttonToPage2);

   //futures - explain this
   await pressingButton;

   //pumpAndSettle is important here so that whole new screen is loaded
   await tester.pumpAndSettle(const Duration(milliseconds: 10));

   expect(find.text("On Location 2"), findsOneWidget);
   expect(find.text("Message1"), findsOneWidget);
  });

test is just a simple async function and can be extract from invocation place to improve code redability

  final WidgetTesterCallback navigateToPage3Test = (tester) async {
    await tester.pumpWidget(NavigationExampleApp());

    final buttonToPage2=find.byKey(Key("gotoPage3"));

    await tester.tap(buttonToPage2);

    await tester.pumpAndSettle();

    expect(find.text("On Location 3"), findsOneWidget);
    expect(find.text("Message2"), findsOneWidget);
  };


  testWidgets("navigation",navigateToPage3Test);

Named Routes

 Widget build(BuildContext context) => MaterialApp(
        title: "Navigation Example",
        initialRoute: '/',
        routes: {
          '/' : (context) => FirstRoute(),
          '/second' : (context) => SecondRoute(Message("TODO", "TODO")),
        },
      );
      ...

   final moveToSecondPage =
      (BuildContext ctx) => () => Navigator.pushNamed(ctx, '/second');

Named Routes - passing value

routes: {
          '/': (context) => FirstRoute(),
          '/second': (context) => SecondRoute(Message("TODO", "TODO")),
          '/third': (context) => ThirdRoute(),
        }

class ThirdRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final Message message = ModalRoute.of(context).settings.arguments;

    return (...)
.....................    

final moveToThirdPage = (BuildContext ctx, Message m) => () => Navigator.pushNamed(
        ctx,
        '/third',
        arguments: m,
      );

Named Routes - receiving value

 RaisedButton(
          child: Text("YES"),
          onPressed: (){
            Navigator.pop(context,"YES");
          },
        ),
        RaisedButton(
          child: Text("NO"),
          onPressed: (){
            Navigator.pop(context,"NO");
          },
        ),


(...)
final OnPressContextBuilder resultFromFourthPage = (BuildContext ctx) => () async {
        final result = await Navigator.pushNamed(
          ctx,
          '/fourth'
        );

        showDialog(context: ctx,builder: (ctx) =>  AlertDialog(title:Text("$result was choosen")));
      };

results matching ""

    No results matching ""