美文网首页
Flutter(十三):路由

Flutter(十三):路由

作者: 林ze宏 | 来源:发表于2020-07-22 09:40 被阅读0次

    1 Flutter 中的路由

    Flutter 中的路由通俗的讲就是页面跳转。在 Flutter 中通过 Navigator 组件管理路由导航。 并提供了管理堆栈的方法。如:Navigator.push 和 Navigator.pop

    Flutter 中给我们提供了两种配置路由跳转的方式:1、基本路由 2、命名路由

    2 基本路由

    通过 Navigator 的 push 和 pop 方法实现路由的跳转和返回。通过构造函数传参,实现路由之间的参数传递。

    import 'package:flutter/material.dart';
    import './Detail.dart';
    
    class HomePage extends StatefulWidget {
      HomePage({Key key}) : super(key: key);
    
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Column(
            children: <Widget>[
              SizedBox(height: 100),
              RaisedButton(
                child: Text('go to Detail'),
                textColor: Theme.of(context).accentColor,
                textTheme: ButtonTextTheme.primary,
                onPressed: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) => Detail(title: '我是从home进入的参数'),
                    ),
                  );
                },
              ),
            ],
          ),
        );
      }
    }
    
    
    
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => Detail(title: '我是从home进入的参数'),
      ),
    );
    
    • Detail.dart 详情页,新的组件外层需要返回 Scaffold 组件。
    import 'package:flutter/material.dart';
    
    class Detail extends StatefulWidget {
      final String title;
      Detail({Key key, this.title}) : super(key: key);
    
      @override
      _DetailState createState() => _DetailState(this.title);
    }
    
    class _DetailState extends State<Detail> {
      final String title;
      _DetailState(this.title);
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          floatingActionButton: FloatingActionButton( // 实现浮动返回按钮
            child: Text('返回'),
            onPressed: () {
              // Navigator.pop(context);
              Navigator.of(context).pop();
            },
          ),
          appBar: AppBar(
            title: Text(this.title ?? '详情'),
          ),
          body: Container(
            child: Column(
              children: <Widget>[
                Text('xxxxx'),
                SizedBox(height: 30),
              ],
            ),
          ),
        );
      }
    }
    
    
    效果

    3 命名式路由

    在 MaterialApp 中配置统一路由。

    • 命名式路由传参,方式一
    main.dart 
    
    import 'package:flutter/material.dart';
    
    import 'tabs/Tabs.dart';
    import 'package:app03/pages/home/Detail.dart';
    import 'res/listData.dart';
    
    void main() {
      runApp(new MyApp());
    }
    
    // 自定义组件
    class MyApp extends StatelessWidget {
      // 1 配置统一命名路由
      final routes = {
        '/detail': (context) => Detail(
            routesArgs:
                ModalRoute.of(context).settings.arguments), // 2 根据组件构造函数参数,传递路由参数
      };
    
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return MaterialApp(
          routes: routes,
          // Scaffold 定义导航头部和页面主要内容
          home: TabsPage(),
          theme: ThemeData(
            primarySwatch: Colors.green,
          ),
        );
      }
    }
    
    
    HomePage.dart
    
    import 'package:flutter/material.dart';
    import './Detail.dart';
    
    class HomePage extends StatefulWidget {
      HomePage({Key key}) : super(key: key);
    
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Column(
            children: <Widget>[
              SizedBox(height: 100),
              RaisedButton(
                child: Text('go to Detail'),
                textColor: Theme.of(context).accentColor,
                textTheme: ButtonTextTheme.primary,
                onPressed: () {
                  Navigator.of(context).pushNamed(
                    "/detail",
                    arguments: {"id": 123}, // 3 使用 arguments 传值,注意类型
                  );
                  // Navigator.push(
                  //   context,
                  //   MaterialPageRoute(
                  //     builder: (context) => Detail(title: '我是从home进入的参数'),
                  //   ),
                  // );
                },
              ),
            ],
          ),
        );
      }
    }
    
    
    Detail.dart
    
    import 'package:flutter/material.dart';
    
    class Detail extends StatefulWidget {
      final String title;
      // 4 定义对应的构造参数,注意类型要对应
      final Map routesArgs;
      Detail({Key key, this.title, this.routesArgs}) : super(key: key);
    
      @override
      _DetailState createState() => _DetailState();
    }
    
    class _DetailState extends State<Detail> {
      @override
      Widget build(BuildContext context) {
        // 5 组件内,获取路由参数
        var args = ModalRoute.of(context).settings.arguments;
        var _args = args as Map; // 如果参数不是为 String 类型,例如 Map 类型等其他类型,需要做强制转换
        print(_args['id']);
    
        return Scaffold(
          floatingActionButton: FloatingActionButton(
            child: Text('返回'),
            onPressed: () {
              // Navigator.pop(context);
              Navigator.of(context).pop();
            },
          ),
          appBar: AppBar(
            title: Text("详情${_args['id']}"),
            // title: Text("详情${(args as Map)['id']}"),
          ),
          body: Container(
            child: Column(
              children: <Widget>[
                Text('xxxxx'),
                SizedBox(height: 30),
              ],
            ),
          ),
        );
      }
    }
    
    
    • 命名式路由传参,方式二
    main.dart 
    
    import 'package:flutter/material.dart';
    
    import 'tabs/Tabs.dart';
    import 'package:app03/pages/home/Detail.dart';
    import 'package:app03/pages/home/FormPage.dart';
    import 'res/listData.dart';
    
    void main() {
      runApp(new MyApp());
    }
    
    // 自定义组件
    class MyApp extends StatelessWidget {
      // 1 配置统一命名路由
      final routes = {
        '/detail': (context) => Detail(), // 2 根据组件构造函数参数,传递路由参数
        '/form': (context, {arguments}) => FormPage(arguments: arguments),
      };
    
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return MaterialApp(
          // routes: routes, // 注意:方式二不用配置,方式一才需要,不然会有问题!!!
          // Scaffold 定义导航头部和页面主要内容
          home: TabsPage(),
          onGenerateRoute: (RouteSettings settings) {
            print('-------${settings.arguments}');
            // 统一处理
            final String name = settings.name;
            final Function pageContentBuilder = this.routes[name];
            if (pageContentBuilder != null) {
              if (settings.arguments != null) {
                final Route route = MaterialPageRoute(
                    builder: (context) =>
                        pageContentBuilder(context, arguments: settings.arguments));
                return route;
              } else {
                final Route route = MaterialPageRoute(
                    builder: (context) => pageContentBuilder(context));
                return route;
              }
            }
          },
          theme: ThemeData(
            primarySwatch: Colors.green,
          ),
        );
      }
    }
    
    
    HomePage.dart
    
    import 'package:flutter/material.dart';
    import './Detail.dart';
    
    class HomePage extends StatefulWidget {
      HomePage({Key key}) : super(key: key);
    
      @override
      _HomePageState createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Column(
            children: <Widget>[
              SizedBox(height: 100),
              RaisedButton(
                child: Text('go to Detail'),
                textColor: Theme.of(context).accentColor,
                textTheme: ButtonTextTheme.primary,
                onPressed: () {
                  Navigator.of(context)
                      .pushNamed("/detail"); // 如果不需要参数就不要写,不然有问题!!!
                  // Navigator.push(
                  //   context,
                  //   MaterialPageRoute(
                  //     builder: (context) => Detail(title: '我是从home进入的参数'),
                  //   ),
                  // );
                },
              ),
              SizedBox(height: 40),
              RaisedButton(
                child: Text('go to Form'),
                textColor: Theme.of(context).accentColor,
                textTheme: ButtonTextTheme.primary,
                onPressed: () {
                  Navigator.pushNamed(context, '/form', arguments: {"id": 20});
                  // Navigator.of(context).pushNamed(
                  //   "/form",
                  //   arguments: {"id": 4445}, // 3 使用 arguments 传值,注意类型
                  // );
                  // Navigator.push(
                  //   context,
                  //   MaterialPageRoute(
                  //     builder: (context) => Detail(title: '我是从home进入的参数'),
                  //   ),
                  // );
                },
              ),
            ],
          ),
        );
      }
    }
    
    
    FormPage.dart
    
    import 'package:flutter/material.dart';
    
    class FormPage extends StatefulWidget {
      final Map arguments;
      // FormPage({this.arguments});
      FormPage({Key key, this.arguments}) : super(key: key);
      // print(arguments);
      @override
      _FormPageState createState() => _FormPageState(arguments: this.arguments);
    }
    
    class _FormPageState extends State<FormPage> {
      final Map arguments;
      _FormPageState({this.arguments});
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          floatingActionButton: FloatingActionButton(
            child: Text('返回'),
            onPressed: () {
              // Navigator.pop(context);
              Navigator.of(context).pop();
            },
          ),
          appBar: AppBar(
            title: Text("Form 表单"),
            // title: Text("详情${(args as Map)['id']}"),
          ),
          body: Container(
            child: Column(
              children: <Widget>[
                Text("我是一个表单页面 ${arguments != null ? arguments['id'] : '0'}"),
                SizedBox(height: 30),
              ],
            ),
          ),
        );
      }
    }
    
    // import 'package:flutter/material.dart';
    
    // class FormPage extends StatelessWidget {
    //   final Map arguments;
    //   FormPage({this.arguments});
    //   @override
    //   Widget build(BuildContext context) {
    //     // print(arguments);
    
    //     return Scaffold(
    //         appBar: AppBar(
    //           title: Text("搜索"),
    //         ),
    //         body: Text("我是一个表单页面 ${arguments != null ? arguments['id'] : '0'}"));
    //   }
    // }
    
    
    Detail.dart
    
    import 'package:flutter/material.dart';
    
    class Detail extends StatefulWidget {
      final String title;
      // 4 定义对应的构造参数,注意类型要对应
      final Map routesArgs;
      Detail({Key key, this.title, this.routesArgs}) : super(key: key);
    
      @override
      _DetailState createState() => _DetailState();
    }
    
    class _DetailState extends State<Detail> {
      @override
      Widget build(BuildContext context) {
        // 5 组件内,获取路由参数
        // var args = ModalRoute.of(context).settings.arguments;
        // var _args = args as Map; // 如果参数不是为 String 类型,例如 Map 类型等其他类型,需要做强制转换
        // print(_args['id']);
    
        return Scaffold(
          floatingActionButton: FloatingActionButton(
            child: Text('返回'),
            onPressed: () {
              // Navigator.pop(context);
              Navigator.of(context).pop();
            },
          ),
          appBar: AppBar(
            title: Text("详情"),
            // title: Text("详情${_args['id']}"),
            // title: Text("详情${(args as Map)['id']}"),
          ),
          body: Container(
            child: Column(
              children: <Widget>[
                Text('xxxxx'),
                SizedBox(height: 30),
              ],
            ),
          ),
        );
      }
    }
    
    

    4 抽离命名路由为单独文件

    main.dart
    
    import 'package:flutter/material.dart';
    
    // import 'tabs/Tabs.dart';
    import 'package:app03/routers/Routers.dart';
    
    import 'res/listData.dart';
    
    void main() {
      runApp(new MyApp());
    }
    
    // 自定义组件
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return MaterialApp(
          // Scaffold 定义导航头部和页面主要内容
          // home: TabsPage(),
          initialRoute: '/', // 抽离 tabs 到路由,需要配置 initialRoute
          onGenerateRoute: onGenerateRoute,
          theme: ThemeData(
            primarySwatch: Colors.green,
          ),
        );
      }
    }
    
    
    Routers.dart
    
    import 'package:flutter/material.dart';
    
    import 'package:app03/tabs/Tabs.dart';
    import 'package:app03/pages/home/Detail.dart';
    import 'package:app03/pages/home/FormPage.dart';
    
    final Map<String, Function> routes = {
      '/': (context) => TabsPage(),
      '/detail': (context) => Detail(), // 2 根据组件构造函数参数,传递路由参数
      '/form': (context, {arguments}) => FormPage(arguments: arguments),
    };
    
    var onGenerateRoute = (RouteSettings settings) {
      print('-------${settings.arguments}');
      // 统一处理
      final String name = settings.name;
      final Function pageContentBuilder = routes[name];
      if (pageContentBuilder != null) {
        if (settings.arguments != null) {
          final Route route = MaterialPageRoute(
              builder: (context) =>
                  pageContentBuilder(context, arguments: settings.arguments));
          return route;
        } else {
          final Route route =
              MaterialPageRoute(builder: (context) => pageContentBuilder(context));
          return route;
        }
      }
    };
    
    
    Tabs.dart(Tabs 组件不变,还是原来的代码)
    
    import 'package:flutter/material.dart';
    
    import 'package:app03/pages/home/HomePage.dart';
    import 'package:app03/pages/category/CategoryPage.dart';
    import 'package:app03/pages/settings/SettingsPage.dart';
    
    class TabsPage extends StatefulWidget {
      TabsPage({Key key}) : super(key: key);
      @override
      _TabsPageState createState() => _TabsPageState();
    }
    
    class _TabsPageState extends State<TabsPage> {
      int currentIndex = 0;
      List listTabs = [
        HomePage(),
        CategoryPage(),
        SettingsPage(),
      ];
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('flutter 标题'),
          ),
          body: this.listTabs[this.currentIndex],
          bottomNavigationBar: BottomNavigationBar(
            currentIndex: this.currentIndex,
            iconSize: 30.0,
            type: BottomNavigationBarType.fixed,
            onTap: (index) {
              setState(() {
                this.currentIndex = index;
              });
            },
            items: [
              BottomNavigationBarItem(
                icon: Icon(Icons.home),
                title: Text('首页'),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.category),
                title: Text('分类'),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.settings),
                title: Text('设置'),
              ),
            ],
          ),
        );
      }
    }
    
    
    目录结构

    5 替换路由和根路由

    CategoryPage.dart (tab 页面进入新的 register 页面)
    
    import 'package:flutter/material.dart';
    
    class CategoryPage extends StatefulWidget {
      CategoryPage({Key key}) : super(key: key);
    
      @override
      _CategoryPageState createState() => _CategoryPageState();
    }
    
    class _CategoryPageState extends State<CategoryPage> {
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Column(
            children: <Widget>[
              Text('Category...'),
              SizedBox(
                height: 30,
              ),
              RaisedButton(
                child: Text('go to 注册'),
                onPressed: () {
                  Navigator.pushNamed(context, '/registerFirst');
                },
              )
            ],
          ),
        );
      }
    }
    
    
    RegisterFirst.dart
    
    import 'package:flutter/material.dart';
    
    class RegisterFirstPage extends StatefulWidget {
      RegisterFirstPage({Key key}) : super(key: key);
    
      @override
      _RegisterFirstPageState createState() => _RegisterFirstPageState();
    }
    
    class _RegisterFirstPageState extends State<RegisterFirstPage> {
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Scaffold(
            appBar: AppBar(
              title: Text('注册'),
            ),
            body: Column(
              children: <Widget>[
                SizedBox(height: 100, width: 50),
                Text('注册步骤一'),
                RaisedButton(
                  child: Text('下一步'),
                  onPressed: () {
                    Navigator.of(context).pushNamed("/registerSecond"); // 普通方式跳转
                    // Navigator.of(context).pushReplacementNamed(
                    //     "/registerSecond"); // 替换路由,Second 路由会替换该 First 路由,所以 Second 返回上一步,就是返回之前 First 路由的上一步。
                  },
                )
              ],
            ),
          ),
        );
      }
    }
    
    
    RegisterSecond.dart(替换路由跳转)
    
    import 'package:flutter/material.dart';
    
    class RegisterSecondPage extends StatefulWidget {
      RegisterSecondPage({Key key}) : super(key: key);
    
      @override
      _RegisterSecondPageState createState() => _RegisterSecondPageState();
    }
    
    class _RegisterSecondPageState extends State<RegisterSecondPage> {
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Scaffold(
            appBar: AppBar(
              title: Text('注册'),
            ),
            body: Column(
              children: <Widget>[
                SizedBox(height: 100, width: 50),
                Text('注册步骤二'),
                RaisedButton(
                  child: Text('下一步'),
                  onPressed: () {
                    Navigator.of(context).pushNamed("/registerThree");
                  },
                )
              ],
            ),
          ),
        );
      }
    }
    
    
    RegisterThree.dart(根路由跳转)
    
    import 'package:flutter/material.dart';
    
    import 'package:app03/tabs/Tabs.dart';
    
    class RegisterThreePage extends StatefulWidget {
      RegisterThreePage({Key key}) : super(key: key);
    
      @override
      _RegisterThreePageState createState() => _RegisterThreePageState();
    }
    
    class _RegisterThreePageState extends State<RegisterThreePage> {
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Scaffold(
            appBar: AppBar(
              title: Text('注册'),
            ),
            body: Column(
              children: <Widget>[
                SizedBox(height: 100, width: 50),
                Text('注册步骤三'),
                RaisedButton(
                  child: Text('确定'),
                  onPressed: () {
                    Navigator.of(context).pushAndRemoveUntil(
                        // 返回到指定到根路由
                        new MaterialPageRoute(builder: (context) => new TabsPage()),
                        (route) => route == null);
                  },
                )
              ],
            ),
          ),
        );
      }
    }
    
    
    • 扩展上面的例子,新增传递 Tabs 参数
    RegisterThree.dart
    
    import 'package:flutter/material.dart';
    
    import 'package:app03/tabs/Tabs.dart';
    
    class RegisterThreePage extends StatefulWidget {
      RegisterThreePage({Key key}) : super(key: key);
    
      @override
      _RegisterThreePageState createState() => _RegisterThreePageState();
    }
    
    class _RegisterThreePageState extends State<RegisterThreePage> {
      @override
      Widget build(BuildContext context) {
        return Container(
          child: Scaffold(
            appBar: AppBar(
              title: Text('注册'),
            ),
            body: Column(
              children: <Widget>[
                SizedBox(height: 100, width: 50),
                Text('注册步骤三'),
                RaisedButton(
                  child: Text('确定'),
                  onPressed: () {
                    Navigator.of(context).pushAndRemoveUntil(
                        // 返回到指定到根路由
                        new MaterialPageRoute(
                            builder: (context) => new TabsPage(index: 1)), // !!!
                        (route) => route == null);
                  },
                )
              ],
            ),
          ),
        );
      }
    }
    
    
    Tabs.dart
    
    import 'package:flutter/material.dart';
    
    import 'package:app03/pages/home/HomePage.dart';
    import 'package:app03/pages/category/CategoryPage.dart';
    import 'package:app03/pages/settings/SettingsPage.dart';
    
    class TabsPage extends StatefulWidget {
      final int index;
      TabsPage({Key key, this.index = 0}) : super(key: key);
      @override
      _TabsPageState createState() => _TabsPageState(this.index);
    }
    
    class _TabsPageState extends State<TabsPage> {
      int currentIndex = 0;
    
      _TabsPageState(index) {
        this.currentIndex = index;
      }
    
      List listTabs = [
        HomePage(),
        CategoryPage(),
        SettingsPage(),
      ];
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('flutter 标题'),
          ),
          body: this.listTabs[this.currentIndex],
          bottomNavigationBar: BottomNavigationBar(
            currentIndex: this.currentIndex,
            iconSize: 30.0,
            type: BottomNavigationBarType.fixed,
            onTap: (index) {
              setState(() {
                this.currentIndex = index;
              });
            },
            items: [
              BottomNavigationBarItem(
                icon: Icon(Icons.home),
                title: Text('首页'),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.category),
                title: Text('分类'),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.settings),
                title: Text('设置'),
              ),
            ],
          ),
        );
      }
    }
    
    

    相关文章

      网友评论

          本文标题:Flutter(十三):路由

          本文链接:https://www.haomeiwen.com/subject/ayjvfktx.html