Flutter Navigator Basics

Navigator is used in two parts:

This section says some basic operations, if you have mastered the basic jump gesture Navigator, please move Flutter Navigator products such as usage

1. The most basic use of the route - Jump in and out

Most App contain many pages used to present different kinds of information. For example: a possible app "Product List Next", click on the item when the time will jump to the corresponding "Product Details" page.

In Flutter, the page is called route (route). Is equivalent to the routing android Activity, ios routing equivalent ViewController, then routed only a widget in the Flutter.

Jump between the two routes need to go through the following three steps

  1. Create two route
  2. Navigate to the second use route Navigator.push ()
  3. Return to the first route using Navigator.pop ()

1.1 create two routes

First, create two pages, as this only to demonstrate the most basic navigation functions, so each page contains only one button. Click on the first page of a button to jump to the second page, click on the second page button to return to the first page

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: () {
            // 点击跳转到第二个route
          },
        ),
      ),
    );
  }
}

class SecondRoute extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Route"),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            // 点击回到第一个route
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

1.2 Use Navigator.push () to jump pages

We use Navigator.push () to switch the page. This method will price a new Route to route the stack, and this stack is managed by the Navigator. So routing stack is come from it? You can ship your own routing stack, or directly use the system provided MaterialPageRoute . This component can easily achieve routing jump animation.

In the method FirstRoute assembly onPress added corresponding jump codes

onPressed: () {
  Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => SecondRoute()),
  );
}

1.3 Use Navigator.pop () to return to the previous page

We use Navigator.pop () to exit and return to SecondRoute FirstRoute, pop () method will return the current route is removed from the stack Route

In onPress method SecondRoute components, add the appropriate return codes

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

The complete code is as follows:

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!'),
        ),
      ),
    );
  }
}

2. do jump by Named Routes (routing table)

In the first section we learned how to use Navigator to do to jump in and out. However, if there is a situation many times to jump to the same page of our project, this approach would result in duplication of a lot of code. The solution is to use Named Route.

In order to use Named Routes, we want to use Navigator.pushNamed () function, we quote the example of the first section, but there are subtle differences in procedure.

  1. Create two route
  2. route definitions created
  3. Jump to SecondRoute use Navigator.pushNamed ()
  4. Return to the first page using Navigator.pop ()

2.1. Creating two Route

And the first code in the same, not repeat them here

2.2. Route definitions created

We need to add two extra in the constructor MaterialApp of property: initialRoute and routes

initialRoutes represents starting route (may be understood as a first page displays the app open), routes represent all the route except initialRoute apart. Specific code as follows

MaterialApp(
  // 定义APP启动时第一个显示的页面,在本例中,initialRoute指代FirstScreen
  initialRoute: '/',
  routes: {
    // 当navigating到‘/’ route时,构建FirstScreen widget
    '/': (context) => FirstScreen(),
    // 当navigating 到"/second" route, 构建SecondScreen widget.
    '/second': (context) => SecondScreen(),
  },
);

It can be seen only when the use Named Routes Route to each defines an alias, so that we can be the basis of this alias Jump

2.3.Navigate to SecondScreen

Use Navigator.pushNamed () to jump when this method is called, routes Flutter would go to an alias defined in the corresponding route, and jump

onPressed: () {
  // 跳转到SecondScreen
  Navigator.pushNamed(context, '/second');
}

2.4 exit pages

Use Navigator.pop ()

onPressed: () {
  // 从第二个页面返回
  Navigator.pop(context);
}

The complete code is as follows:

import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    title: 'Named Routes Demo',
    initialRoute: '/',
    routes: {
      '/': (context) => FirstScreen(),
      '/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: () {
            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: () {
            Navigator.pop(context);
          },
          child: Text('Go back!'),
        ),
      ),
    );
  }
}

3. traditional values ​​in the Named Route

The previous two just to say how to jump in and out, but in the actual project development is certainly a problem of data exchange between ultimately pages.

Navigator.pushNamed () function is not a null reference, what is the source of the method

@optionalTypeArgs
  static Future<T> pushNamed<T extends Object>(
    BuildContext context,
    //路由路径
    String routeName, {
    //携带的参数
    Object arguments,
   }) {
    return Navigator.of(context).pushNamed<T>(routeName, arguments: arguments);
  }

arguments are carried jump parameters, it is an Object, means that you can pass any type of argument, but how after the jump to the next page to get the value out of it, looks like there is no corresponding "key" yet. Here the traditional values ​​and value complete step

  1. Ready data you want to pass
  2. Create a page to obtain the transfer of data
  3. The registration page in routes table
  4. Jump

3.1. Preparing the transfer of data

First, we define good data to be transferred. Here we pass two parameters, title and message, and encapsulates them in a Bean

class ScreenArguments {
  final String title;
  final String message;

  ScreenArguments(this.title, this.message);
}

3.2. Create a page to accept the transfer of data

Create a new page to accept and display parameters passed. As we mentioned above how to get the arguments, we use ModalRoute.of () can be friends. This method can get the 3 parameters of the current routing portable.

class ExtractArgumentsScreen extends StatelessWidget {
  static const routeName = '/extractArguments';

  @override
  Widget build(BuildContext context) {
    //获取传递的参数
    final ScreenArguments args = ModalRoute.of(context).settings.arguments;

    return Scaffold(
      appBar: AppBar(
        title: Text(args.title),
      ),
      body: Center(
        child: Text(args.message),
      ),
    );
  }
}

3.3. Register a new page

Of course, the use of pushNamed sure to register the page jump routes in the table, so the ExtractArgumentsScreen registered into

MaterialApp(
  routes: {
    ExtractArgumentsScreen.routeName: (context) => ExtractArgumentsScreen(),
  },     
);

3.4 Jump

Everything is ready, we use pushNamed to achieve the jump, and ready to pass parameters in the past

RaisedButton(
  child: Text("使用pushNamed携带参数跳转"),
  onPressed: () {
    //点击事件,触发跳转
    Navigator.pushNamed(
      context,
      ExtractArgumentsScreen.routeName,
      arguments: ScreenArguments(
        '我是被传递的title',
        '我是被传递的message.',
      ),
    );
  },
);

Extended: From Section 3.2 we know ModalRoute.of () can get the parameters passed to it, but our case is the use of passing parameters pushNamed, if Navigator.push () can pass parameters to get thing? For example like this:

Navigator.push(
    context,
    MaterialPageRoute(
        builder: (context) => ExtractArgumentsScreen(),
        settings: RouteSettings(
            arguments: ScreenArguments(
                '我是title',
                '我是message.',
             ),
         ),
     ),
   );

First answer: Both methods can be used by value ModalRoute.of () to the value, because the two final jump method will be called Future <T> push <T extends Object> (Route <T> route) , are interested can go to view source code, there is not much into details.

3.5. Another way to jump

In addition to the above mentioned we jump way, we can also use onGenerateRoute to jump by value.

In this example the value is still passed our title and Message, and packaged into a ScreenArguments entity class, page parameters need to be increased to accept a method configured to receive the two values

class PassArgumentsScreen extends StatelessWidget {
  static const routeName = '/passArguments';

  final String title;
  final String message;

  //定义一个构造方法
  const PassArgumentsScreen({
    Key key,
    @required this.title,
    @required this.message,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Text(message),
      ),
    );
  }
}

Add onGnerateRoute property in the MaterialApp

MaterialApp(
  
  onGenerateRoute: (settings) {
    // 判断当前route,分别进行处理
    if (settings.name == PassArgumentsScreen.routeName) {
      // 将settings.arguments转换为正确的类型 ScreenArguments.
      final ScreenArguments args = settings.arguments;

      //通过构造方法传值
      return MaterialPageRoute(
        builder: (context) {
          return PassArgumentsScreen(
            title: args.title,
            message: args.message,
          );
        },
      );
    }
  },
);

Then look at the code uses onGenerateRoute way to do jumps

Navigator.push(
    context,
    MaterialPageRoute(
        builder: (context) => ExtractArgumentsScreen(),
        settings: RouteSettings(
            arguments: ScreenArguments(
                '我是title',
                '我是message.',
             ),
         ),
     ),
   );

4. carry parameters Exit

We have learned how to jump, exit, carry parameters jump parameter passed to receive. But when a page exit parameters of how to carry it? For example, we opened a contact Select page, click a quit item after page, we need to know what choice of contact information yes.

Speaking in front of our exit pages just call Navigator.pop (context) on the line, in fact, this method also has an optional parameter, with a look at the complete code

@optionalTypeArgs
static bool pop<T extends Object>(BuildContext context, [ T result ]) {
  return Navigator.of(context).pop<T>(result);
}

Here the second parameter T is carried on exit page parameters, let's take a detailed look at Navigator.pop () usage

  1. Create a page called HomeScreen and add a button to jump to SelectionScreen
  2. Creating SelectionScreen, this page contains two buttons, the effect of the page and click on Quit all carry different return values
  3. Receiving a return value HomeScreen and displays with a Snackbar

4.1 Creating a page called HomeScreen and add a button to jump to SelectionScreen

class SelectionButton extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      onPressed: () {
        _navigateAndDisplaySelection(context);
      },
      child: Text('Pick an option, any option!'),
    );
  }

  //点击跳转到SelectionScreen并接收返回值
  _navigateAndDisplaySelection(BuildContext context) async {
    // Navigator.push returns a Future that completes after calling
    // Navigator.pop on the Selection Screen.

//调用Navigator.push()会返回一个Furture,根据这个Future可以接收页面返回的参数,这个下面再讲
    final result = await Navigator.push(
      context,
      // Create the SelectionScreen in the next step.
      MaterialPageRoute(builder: (context) => SelectionScreen()),
    );
  }
}

4.2 Creating SelectionScreen, this page contains two buttons, the effect of the page and click on Quit all carry different return values

class SelectionScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Pick an option'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                onPressed: () {
                  // 退出页面,并携带一个返回值‘Yep!' 
                  Navigator.pop(context, 'Yep!');
                },
                child: Text('Yep!'),
              ),
            ),
            Padding(
              padding: const EdgeInsets.all(8.0),
              child: RaisedButton(
                onPressed: () {
                  // 退出页面,并携带一个返回值 "Nope"
                  Navigator.pop(context, 'Nope!');
                },
                child: Text('Nope.'),
              ),
            )
          ],
        ),
      ),
    );
  }
}

4.3 HomeScreen return value received and displayed by a Snackbar

_navigateAndDisplaySelection(BuildContext context) async {
  final result = await Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => SelectionScreen()),
  );

  String value = result as String;
  Scaffold.of(context)
    ..removeCurrentSnackBar()
    ..showSnackBar(SnackBar(content: Text("$value")));
}

 

 

 

 

 

 

 

 

 

 

 

 

 

Published 21 original articles · won praise 21 · views 20000 +

Guess you like

Origin blog.csdn.net/u013894711/article/details/100600139
Recommended