Flutter 底部导航栏页面的状态保持

使用 Flutter 实现带底部导航栏的 APP 主页面,根节点使用 Scaffold,再配置 bottomNavigationBar 设置点击事件通过调用 setState() 方法在 build 返回不同的页面即可。但运行后会发现,点击切换页面后之前的页面状态无法保持,切换页面后再切回之前的页面,页面显示的数据会重绘为初始状态。这是因为 flutter 页面默认情况下每次都是返回的一个新的对象,重新绘制再界面的,不做任何处理的情况下自然不能保留数据。要解决这个问题,有下面的三种实现方式:

一、Stack + OffStage + TickerMode 堆叠

简单粗暴,跟 Android 开发中在 FrameLayout 中堆叠 View,再根据需要控制部分 View 的显示于隐藏,在构建页面时 body 直接返回一个 Stack 对象,子 widget 即为要显示的所有页面:

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      body: Stack(children: <Widget>[
        _makePage(0),
        _makePage(1),
        _makePage(2),
        _makePage(3),
      ]),
      bottomNavigationBar: _getNavigationBar(),
    );
    
 /*
   * Stack 方式创建页面
   */
  Widget _makePage(int index) {
    return Offstage(
        offstage: this._currentIndex != index,
        child: TickerMode(enabled: this._currentIndex == index, child: _pageList[index]));
  }

通过 TickerMode 的 enabled 来控制页面是否显示,当页面的 index 为当期选中的 index 时显示否则隐藏。

二、IndexedStack 控制页面的显示

类似 Android 中 FragementTransManager 控制 fragement 的显示隐藏,这与第一种方式没有太大本质上的区别,只不过是显示判断逻辑交给 IndexedStack 内部自动完成,与第一种方式相比代码量会少很多

    // IndexStack 方式
    return new Scaffold(
      body: IndexedStack(index: _currentIndex, children: _pageList),
      bottomNavigationBar: _getNavigationBar(),
    );

三、PageView

PageView 类似于 Android 中的 ViewPager 支持,页面之间的滑动切换。这种方式需要每一个要保持状态的 Widget 状态管理类实现 AutomaticKeepAliveClientMixin<Widget>,并且 wangKeepAlive 返回 true。伪代码如下:

class WidgetState extends State<Widget>
    with AutomaticKeepAliveClientMixin<Widget> {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Widget;
  }

  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;

这个样 PageView 在切换时 flutter 内部就会知道你想要保持对应页面的状态,在页面切换时会将数据保留下来。这种方式是支持滑动切换页面的

总结

不需要支持左右滑动切换页面直接使用第二种方式实现导航栏效果,需要滑动切换页面效果则使用第三种方式。不推荐使用第一种方式实现此功能
Demo

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 7,137评论 4 39
  • Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可...
    Cat9527阅读 393评论 0 1
  • 原文在此,此处只为学习 Widget与ElementWidget主要接口Stateless WidgetState...
    lltree阅读 3,507评论 0 1
  • 作为系列文章的第二篇,本篇将为你着重展示:如何搭建一个通用的Flutter App 常用功能脚手架,快速开发一个完...
    恋猫月亮阅读 31,755评论 13 96
  • 今年国庆中秋双节一起,放假八天,作为一个名为朝九晚五实为朝七晚七的上班族,我没有去追寻诗和远方,也没敢回家接受父辈...
    莫里木禾阅读 202评论 2 1