美文网首页All in FlutterFlutter
Flutter局部路由实现方案

Flutter局部路由实现方案

作者: 吉原拉面 | 来源:发表于2019-05-15 16:34 被阅读30次

  本文主要讲一个Flutter中局部替换路由的方案,在实际开发中,需要局部替换的情况似乎还蛮多的,所以还是讲一下这个小技巧把。
  效果图:

part_navigator.gif
  实现其实超级简单,主要是在压路由的时候注意下用哪个context就行了。
  代码:https://gist.github.com/yumi0629/a22bc590bbe7a3d10d3436afb27c7043

  首先页面分成两部分,上下的appBar和bottomNavigationBar是在局部替换的时候不变的,中间的body是需要局部替换的。我们知道,路由的替换是Navigator操控的,所以中间的body部分,我们只要自己维护一个Navigator,就可以实现局部替换了。而Flutter早就为我们设计好了,Navigator是一个Widget,我们可以直接拿来用:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('PartNavigator'),
      ),
      body: Navigator(
        // 这里维护局部路由
      ),
      bottomNavigationBar: Container(
        height: 40.0,
        color: Colors.red,
      ),
    );
  }

  定义一个Navigator很简单,点进文档就能看到很详细的example,这里再次感谢Flutter爸爸文档写得真良心!

Navigator(
        initialRoute: 'part/part1',
        onGenerateRoute: (RouteSettings settings) {
          RoutePageBuilder builder;
          switch (settings.name) {
            case 'part/part1':
              builder = (_, __, ___) => PartPage1(
                    pageContext: context,
                  );
              break;
            case 'part/part2':
              builder = (_, __, ___) => PartPage2(
                    pageContext: context,
                  );
              break;
            default:
              throw Exception('Invalid route: ${settings.name}');
          }
          return PageRouteBuilder(
            pageBuilder: builder,
            transitionDuration: const Duration(milliseconds: 0),
          );
        },
      )

  其中,onGenerateRoute是必传的,initialRouteonGenerateRouteonUnknownRoute都是定义路由跳转的,他们之间有优先级关系,这个我以前讲过,还是再说一遍吧:
  Navigator会按照initialRoute----onGenerateRoute---->onUnknownRoute的顺序去寻找路由:

  • initialRoute,也就是初始路由;
  • onGenerateRoute用来处理路由,我们可以在里面定义路由映射,所以一般返回非空值;
  • onUnknownRoute如果说某个路由上面都没处理,那么就会由onUnknownRoute来处理这个路由。
      上述例子中我们将part1控件作为初始路由,我们在里面写两个按钮,一个按钮点击后做布局跳转到part2,另一个按钮点击后做全局的页面跳转:
class PartPage1 extends StatelessWidget {
  final BuildContext pageContext;

  const PartPage1({Key key, this.pageContext}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text.rich(
          TextSpan(
              style: TextStyle(fontSize: 20.0),
              text: 'This is part',
              children: [
                TextSpan(
                  style: TextStyle(fontSize: 40.0, color: Colors.red),
                  text: ' 1',
                )
              ]),
        ),
        RaisedButton(
          onPressed: () {
            Navigator.of(context).pushNamed('part/part2');
          },
          child: Text('To Part 2'),
        ),
        RaisedButton(
          onPressed: () {
            Navigator.of(pageContext)
                .push(MaterialPageRoute(builder: (_) => AnotherPage()));
          },
          child: Text('To Another Page'),
        )
      ],
    );
  }
}

  我们可以看到,两次跳转时获取Navigator的context明显是不一样的,我开头就说了,压路由一定要使用对应的Navigator的context。PartPage1中的context是局部Navigator给它的,所以维护的是局部路由;而变量pageContextScaffold给它的,所以它并不属于Navigator。所以,Navigator.of(context)Navigator.of(pageContext)自然不是同一个实例。
  到这里,很多小伙伴肯定会问了,Scaffold的Navigator是哪里来的呢?翻下源码就知道啦,Flutter在WidgetsApp中维护了一个全局的路由池来供开发者使用:

@override
  Widget build(BuildContext context) {
    Widget navigator;
    if (_navigator != null) {
      navigator = Navigator(
        key: _navigator,
        // If window.defaultRouteName isn't '/', we should assume it was set
        // intentionally via `setInitialRoute`, and should override whatever
        // is in [widget.initialRoute].
        initialRoute: WidgetsBinding.instance.window.defaultRouteName != Navigator.defaultRouteName
            ? WidgetsBinding.instance.window.defaultRouteName
            : widget.initialRoute ?? WidgetsBinding.instance.window.defaultRouteName,
        onGenerateRoute: _onGenerateRoute,
        onUnknownRoute: _onUnknownRoute,
        observers: widget.navigatorObservers,
      );
    }

相关文章

网友评论

    本文标题:Flutter局部路由实现方案

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