• Flutter入门-路由


    路由

    Flutter使用路由来定义页面之间的跳转,类似Vue。Flutter使用Navigator组件来管理路由导航。

    方法:

    • Navigator.push,跳转
    • Navigator.pop, 返回上一级,如果是对话框,会关闭对话框。

    普通路由

    使用场景:在一些小型项目中推荐使用。

    核心代码

    跳转

     Navigator.of(context).push(MaterialPageRoute(
                    builder: (context) => const SearchPage(),
                  ));
     //传值             
     Navigator.of(context).push(MaterialPageRoute(
                    builder: (context) => FormPage(title: "我是传递过来的值"),
                  ));              
    
    

    返回或关闭

     Navigator.of(context).pop();
    

    演示案例

    1、主页面

    class HomePage extends StatefulWidget {
      const HomePage({super.key});
    
      
      State<HomePage> createState() => _HomePageState();
    }
    
    class _HomePageState extends State<HomePage> {
      
      Widget build(BuildContext context) {
        return Column(
          children: [
            //按钮1,使用漂浮按钮,设置点击事件,点击的时候,push到另一个页面
            ElevatedButton(
                onPressed: () {
                  Navigator.of(context).push(MaterialPageRoute(
                    builder: (context) => const SearchPage(),
                  ));
                },
                child: const Text('跳转到搜索页面')),
    
            //按钮2,跳转传值,通过构造函数传值。
            ElevatedButton(
                onPressed: () {
                  Navigator.of(context).push(MaterialPageRoute(
                    builder: (context) => FormPage(title: "我是传递过来的值"),
                  ));
                },
                child: const Text('跳转到表单页面并传值')),
          ],
        );
      }
    }
    

    2、SearchPage,不传值

    使用Scaffold,跳转过来的页面都会自带返回箭头,点击就会执行pop。

    class SearchPage extends StatelessWidget {
      const SearchPage({super.key});
    
      
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text("我是搜索页面"),
          ),
          body: const Text("搜索页面内容区域"),
        );
      }
    }
    

    3、FormPage,传值
    使用Scaffold,跳转过来的页面都会自带返回箭头,点击就会执行pop

    class FormPage extends StatelessWidget {
      String title;
      //设置默认值,没有传值将会使用默认值
      FormPage({super.key, this.title = "表单"});
    
      
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(title),
          ),
          body: ListView(
            children: const [
              ListTile(
                title: Text("item标题"),
                subtitle: Text("item描述"),
              ),
            ],
          ),
          //也可以手动添加返回按钮,使用floatingActionButton
          floatingActionButton: FloatingActionButton(
            child: const Text('返回'),
            onPressed: () {
              Navigator.of(context).pop();
            },
          ),
        );
      }
    }
    
    

    命名路由

    如果是大型项目,路由比较多,我们希望可以统一管理所有的路由,就可以使用命名路由。

    基本使用

    1、定义命名路由

    class MyApp extends StatelessWidget {
      
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Welcome to Flutter',
          theme: ThemeData(primarySwatch: Colors.blue),
          home: Tabs(),
          routes: {
            '/form': (context) => FormPage(),
            '/search': (context) => SearchPage(),
             
          },
        );
      }
    }
    

    路由的名称,我们也可以根据模块进行区分

    • /user/login
    • /user_login
    • user_login

    怎样都可以。

    2、页面跳转

    直接通过 Navigator.pushNamed()进行页面跳转。

    return Column(
      children: [
        ElevatedButton(
            onPressed: () {
              //Navigator.of(context).push(MaterialPageRoute(builder: (context) => SearchPage()));
              Navigator.pushNamed(context, '/search');
            },
            child: Text('跳转到搜索页面')),
        ElevatedButton(
            onPressed: () {
              // Navigator.of(context).push(MaterialPageRoute(builder: (context) {
              //   //return FormPage(title: "我是传递过来的值");
              //   return FormPage();
              // }));
              Navigator.pushNamed(context, '/form');
            },
            child: Text('跳转到表单页面并传值')),
      ],
    

    命名路由传值

    1、定义路由,改造后

    class MyApp extends StatelessWidget {
    
        //1、抽取路由定义
      final routes = {
        '/search': (context) => SearchPage(),
        '/form': (context, {arguments}) => FormPage(arguments: arguments),
      };
    
      
      Widget build(BuildContext context) {
        return MaterialApp(
            title: 'Welcome to Flutter',
            theme: ThemeData(primarySwatch: Colors.blue),
            home: Tabs(),
    
            //2、路由监听,类似拦截器的效果,固定写法,固定代码
            onGenerateRoute: (RouteSettings settings) {
              //统一处理,进行了非空检查,也就是末尾添加感叹号
              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;
                }
              }
            });
      }
    }
    

    2、传递数据

    return Column(
      children: [
        ElevatedButton(
            onPressed: () {
            //命名路由,不传值
              Navigator.pushNamed(context, '/search');
            },
            child: Text('跳转到搜索页面')),
        ElevatedButton(
            onPressed: () {
              //命名路由,不传值
              //Navigator.pushNamed(context, '/form');
              
              //命名路由,传值写法
              Navigator.pushNamed(context, '/form', arguments: {
                "title": "表单",
                "name": "章三",
                "desc": "我是描述内容",
              });
            },
            child: Text('跳转到表单页面并传值')),
      ],
    );
    

    3、接收数据

    class FormPage extends StatelessWidget {
      //接收传递的参数
      final arguments;
      FormPage({this.arguments});
    
      
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            //取出传递过来的数据
            title: Text(arguments != null ? arguments['title'] : "default"),
          ),
          body: ListView(
            children: [
            //取出传递过来的数据
              ListTile(
                title: Text(arguments != null ? arguments['name'] : "default"),
                subtitle: Text(arguments != null ? arguments['desc'] : 'default'),
              ),
            ],
          ),
          //手动添加返回按钮
          floatingActionButton: FloatingActionButton(
            child: Text('返回'),
            onPressed: () {
              Navigator.of(context).pop();
            },
          ),
        );
      }
    }
    

    路由替换

    不使用路由替换

    ElevatedButton(
      onPressed: () {
        //这种方式跳转,下一页返回的时候直接返回到这一页
        Navigator.pushNamed(context, '/register2');
      },
      child: const Text("下一步")),
    

    使用路由替换

    ElevatedButton(
      onPressed: () {
        //这种方式跳转,下一页返回返回到当前页的上一页。
        Navigator.pushReplacementNamed(context, '/register2');
      },
      child: const Text("下一步")),
    

    区别:

    • 不使用路由替换,跳转到下一页之后,点击返回按钮,返回到当前页。
    • 使用路由替换,跳转到下一页之后,点击返回按钮,返回到当前页的上一页。
    返回根路径

    假设注册分好几步,注册成功后,直接跳转到首页。通过Navigator.pushAndRemoveUntil可以直接跳转到指定的路由,并清空route

    ElevatedButton(
      onPressed: () {
        Navigator.pushAndRemoveUntil(
          context,
          MaterialPageRoute(builder: (context) => const Tabs(index: 2)),
          (route) => route == null,
        );
      },
      child: const Text("完成注册")),
    

    抽取路由文件

    //配置路由
    final routes = {
      '/': (context) => const Tabs(),
      '/search': (context) => const SearchPage(),
      '/form': (context, {arguments}) => FormPage(arguments: arguments),
      '/product': (context) => const ProductPage(),
      '/productInfo': (context, {arguments}) => ProductInfoPage(arguments: arguments),
      '/login': (context) => const LoginPage(),
      '/register1': (context) => const RegisterFirstPage(),
      '/register2': (context) => const RegisterSecondPage(),
      '/register3': (context) => const RegisterThirdPage(),
      '/userCenter': (context) => const UserCenterPage(),
    };
    
    /*
     *  这个方法是固定写法,功能就像是一个拦截器。 
     */
    var onGenerateRoute = (RouteSettings settings) {
      //统一处理,进行了非空检查,也就是末尾添加感叹号
      final String name = settings.name!;
      debugPrint("访问的路由地址名称=$name");
      final Function pageContentBuilder = routes[name]!;
    
      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;
      }
    };
    
  • 相关阅读:
    1560分钟一节课VUE项目从入门到精通
    Mybatis-Plus--LambdaQueryChainWrapper--使用/实例
    SpringMVC-CRUD与文件上传、文件下载
    下个牛市来临时,哪些跨链应用有望成为新独角兽并值得提前布局?
    Scrapy 下载多层请求、多页图片 (重写get_media_requests、file_path方法)
    ElementUI之CUD+表单验证
    angular测试API
    【Express连接MySQL数据库】
    flutter项目引入本地静态图片资源并展示
    解决aspose在linux上中文乱码的方法
  • 原文地址:https://blog.csdn.net/Z18789231876/article/details/127089142