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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章