Flutter11 路由、页面传值、Navigator

本文对应github地址Flutter11,若是因为github调整致使资源找不到,请访问githubgit

路由

  1. 简介github

    • iOS中页面跳转经过NavigationController,而后pushViewController,Android中能够初始化Intent而后startActivity,Flutter中则路由(Route)方式
    • 程序启动后路由栈第一个(最底部)实例 MaterialApp(home: Screen1())
    • 命名路由,对页面起别名(惟一字符串),但通常用有意义字符串,如 '/'表示根页面,'/login'表示登陆页等
  2. 静态路由pushbash

    • 静态路由在MeterialApp初始化时配置routes参数,经过起的别名(命名路由)进行跳转
    • 新页面为配置的固定页面,且跳转时参数也是固定的
    • 调用方法为pushNamed()
    // MaterialApp初始化时配置Key-Value
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primaryColor: Colors.red,
            primarySwatch: Colors.blue,
          ),
          home: DDYBottomBar(),
          showPerformanceOverlay: false,
          routes: {
            '/home/qrcode': (BuildContext context) => QRCodeScanner(title: '0',),
            '/home_qrcode': (BuildContext context) => QRCodeScanner(title: '1',),
            '+home_qrcode': (BuildContext context) => QRCodeScanner(title: '2',),
          },
        );
      }
    }
    
    // 在须要的地方调用['/home/qrcode'只是字符串名字,并非真正路径,这样仿路径是为了可读性]
    // Navigator.pushNamed(context, '/home/qrcode');
    // Navigator.pushNamed(context, '/home_qrcode');
    // Navigator.pushNamed(context, '+home_qrcode');
    Navigator.of(context).pushNamed('+home_qrcode');
    复制代码
  3. 动态路由push闭包

    • 动态路由在须要跳转时生成要跳转的页面对象,传递想要的参数,而后调用push()函数
    // Navigator.push(context, MaterialPageRoute(builder: (context) => QRCodeScanner()));
    // Navigator.of(context).push(MaterialPageRoute(builder: (_) => QRCodeScanner()));
    Navigator.of(context).push(MaterialPageRoute(builder: (context) => QRCodeScanner()));
    复制代码
  4. 路由popless

    • pop()方法中可添加回调数据
    // Navigator.of(context).pop();
    // Navigator.pop(context);
    Navigator.of(context).pop('回调数据');
    复制代码
  5. 页面传值异步

  • 正向传值直接经过简单构造函数参数方式便可async

  • 反向传值,不一样风格其实都同样,建议第一种ide

    // 风格1
    pushQRCodeScannerAndCallbackData1() {
      Navigator.of(context).push(MaterialPageRoute(builder: (context) => QRCodeScanner())).then((value){
        print('1 $value');
      });
    }
    // 风格2
    pushQRCodeScannerAndCallbackData2() {
      Future callbackFuture = Navigator.of(context).push(MaterialPageRoute(builder: (_) => QRCodeScanner()));
      callbackFuture.then((value){
        print('2 $value');
      });
    }
    // 风格3
    pushQRCodeScannerAndCallbackData3() async {
      // 若是知道类型
      String callbackString = await Navigator.of(context).push<String>(
          MaterialPageRoute(builder: (context){
            // 正向传值直接经过简单构造函数参数方式便可
            return QRCodeScanner(title:'I am 3');
          })
      );
      if (callbackString != null) {
        print('3 ${callbackString}');
      }
    }
    
    
    // pop()函数参数值即为反向传回的数据
    Navigator.of(context).pop('回调数据');
    复制代码
  • 还能够经过闭包做为参数进行传值函数

    pushQRCodeGenerator() {
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (context) => QRCodeGenerator((String value) {
            print('QRCodeGenerator callback $value');
          }),
        ),
      );
    }
    
    
    // 调用
    IconButton(
      icon: Icon(Icons.print), 
        onPressed: () {
          if (widget.callbackFunction != null) {
            widget.callbackFunction('回调数据');
          }
        },
    ),
    复制代码
  1. 定制路由(自定义路由,自定义转场)
  • 继承路由子类,如:PopupRoute、ModalRoute 等ui

  • 使用 PageRouteBuilder 类经过回调函数定义路由

    • 从下向上弹出,从上向下收回
    pushQRCodeScannerWithCustomAnimation() {
      Navigator.push(
        context,
        PageRouteBuilder(pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
          return QRCodeScanner();
        }, transitionsBuilder: (context, animation, secondaryAnimation, child) {
          return transitionAnimation(animation, child);
        }),
      );
    }
    
    static SlideTransition transitionAnimation(Animation<double> animation, Widget child) {
      return SlideTransition(
        position: Tween<Offset>(
          begin: const Offset(0.0, 1.0),
          end: const Offset(0.0, 0.0),
        ).animate(animation),
        child: child,
      );
    }
    复制代码
    • 页面旋转淡出的效果
    pushQRCodeScannerWithCustomAnimation2() async {
      // 页面旋转淡出的效果
      transitionAnimation(Animation<double> animation, Widget child) {
        return FadeTransition(
          opacity: animation,
          child: RotationTransition(
            turns: Tween<double>(begin: 0.7, end:1.0).animate(animation),
            child: child,
          ),
        );
      }
    
      Navigator.push(
        context,
        PageRouteBuilder(
          pageBuilder: (context, _, __) => QRCodeScanner(),
          transitionDuration: const Duration(milliseconds: 1000),
          transitionsBuilder: (_, animation, __, child) => transitionAnimation(animation, child),
        ),
      ).then((value){
        Scaffold.of(context).showSnackBar(
          SnackBar(
            content: Text(value),
            duration: const Duration(seconds: 3),
          ),
        );
      });
    }
    复制代码
  1. 嵌套路由
  • 一个应用程序可使用多个路由导航器

  • 可将一个导航器嵌套在另外一个导航器下方使用,例如选项卡式导航,用户注册,订单与结帐页等

    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          initialRoute: '/',
          routes: {
            '/': (BuildContext context) => HomePage(),
            '/signup': (BuildContext context) => SignUpPage(),
          },
        );
      }
    }
    
    class SignUpPage extends StatelessWidget {
     @override
     Widget build(BuildContext context) {
       return Navigator(
         initialRoute: 'signup/personal_info',
         onGenerateRoute: (RouteSettings settings) {
           WidgetBuilder builder;
           switch (settings.name) {
             case 'signup/personal_info':
               // 我的信息完毕后到 'signup/choose_credentials'.
               builder = (BuildContext _) => CollectPersonalInfoPage();
               break;
             case 'signup/choose_credentials':
               // 选完credentials 调用 'onSignupComplete()'.
               builder = (BuildContext _) => ChooseCredentialsPage(
                 onSignupComplete: () {
                   // 回到路由根页面 '/' (HomePage)
                   Navigator.of(context).pop();
                 },
               );
               break;
             default:
               throw Exception('Invalid route: ${settings.name}');
           }
           return MaterialPageRoute(builder: builder, settings: settings);
         },
       );
     }
    }
    复制代码

Navigator

  1. 继承自StatefulWidget,路由堆栈的管理者
  2. 静态方法详解
  • pushNamed
  • pushReplacementNamed
  • popAndPushNamed
  • pushNamedAndRemoveUntil
  • push
  • pushReplacement
  • pushAndRemoveUntil
  • replace
  • replaceRouteBelow
  • canPop
  • maybePop
  • popUntil
  • removeRoute
  • removeRouteBelow
push和pushName

pushName结合配置routes,利用命名路由形式将指定页面实例(带固定参数)入栈,而push则是在须要跳转时生成要跳转的页面对象,传递想要的参数,二者运行效果没差异。

pushReplacement和pushReplacementNamed

二者都是取代栈顶元素,运行效果没差异。

popAndPushNamed

顾名思义,先pop而后push

pushAndRemoveUntil 和 pushNamedAndRemoveUntil

二者都是入栈新页面删除除该页面实例外其余栈内实例,将该实例做为新栈底,运行效果没差异。可用在注册登陆页登陆后跳转,防止能返回注册登陆页

canPop

判断是否能够pop,若是能够返回true,不然返回false

maybePop

表示在该页面尝试pop,若是能够则pop到前一页,不然仍停在该页面,丢弃该次pop

popUntil

pop回栈内(该页面实例如下)指定页面实例,如 Navigator.popUntil(context, ModalRoute.withName('/home'));,回到配置名为home的页面。

其余知识点

  1. 去除返回按钮 AppBar中

    automaticalImplyLeading: false
    复制代码
  2. Popup routes (弹出路由)

路由不必定要遮挡整个屏幕。 PopupRoutes 使用 ModalRoute.barrierColor 覆盖屏幕,ModalRoute.barrierColor 只能部分不透明以容许当前屏幕显示。 弹出路由是“模态”的,由于它们阻止了对下面其余组件的输入。

有一些方法能够建立和显示这类弹出路由。 例如:showDialog,showMenu 和 showModalBottomSheet。 如上所述,这些函数返回其推送路由的 Future(异步数据,参考下面的数据部分)。 执行能够等待返回的值在弹出路由时执行操做。

还有一些组件能够建立弹出路由,如 PopupMenuButton 和 DropdownButton。 这些组件建立 PopupRoute 的内部子类,并使用 Navigator 的push 和 pop 方法来显示和关闭它们。

参考

上一页 Flutter10 Icon、Color、Tabbar、BottomNavigationBar
下一页 Flutter12 ListBody、ListView、ListTile

相关文章
相关标签/搜索