Flutter tab切換保持頁面狀態的兩種方法


當通過底部tabBar將頁面在“首頁”和“分類”之間進行切換的時候,每一次進入頁面的時候該頁面的數據都會重新加載。那么如何讓頁面保持原來的狀態,而不是每次都要重新加載刷新數據呢?有兩種方式。

第一種方式:采用IndexdStack

IndexdStack和Stack一樣,都是層布局控件,可以在一個控件上面放置另一個控件,但唯一不同的是,IndexdStack在同一時刻只能顯示子控件中的一個控件,通過index屬性來設置顯示的控件。

配置底部導航的核心代碼如下:

import 'package:flutter/material.dart';
import 'package:flutter_jdshop/pages/tabs/CategoryPage.dart';
import 'package:flutter_jdshop/pages/tabs/HomePage.dart';
import 'package:flutter_jdshop/pages/tabs/ShoppingCartPage.dart';
import 'package:flutter_jdshop/pages/tabs/UserPage.dart';

class Tabs extends StatefulWidget {
  Tabs({Key key}) : super(key: key);

  _TabsState createState() => _TabsState();
}

class _TabsState extends State<Tabs> {

  int _currentIndex = 0;//記錄當前選中哪個頁面

  List<Widget> _pages = [
    HomePage(),
    CategoryPage(),
    ShoppingCartPage(),
    UserPage()
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("JDShop")),
      body: this._pages[this._currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        fixedColor: Colors.red,//底部導航欄按鈕選中時的顏色
        type: BottomNavigationBarType.fixed,//底部導航欄的適配,當item多的時候都展示出來
        currentIndex: this._currentIndex,
        onTap: (index){
          setState(() {
            this._currentIndex = index;
          });
        },
        items: [
          BottomNavigationBarItem(icon: Icon(Icons.home), title: Text("首頁")),
          BottomNavigationBarItem(icon: Icon(Icons.category), title: Text("分類")),
          BottomNavigationBarItem(icon: Icon(Icons.shopping_cart), title: Text("購物車")),
          BottomNavigationBarItem(icon: Icon(Icons.people), title: Text("我的"))
        ],
      ),
    );
  }
}

此時還是不可以保持頁面狀態的。

這里我們將body由

body: this._pages[this._currentIndex],

替換成

body: IndexedStack(
        index: this._currentIndex,
        children: this._pages,
      ),

這樣就能夠實現保持頁面狀態了,效果如下:

我們可以看到,此時,頁面的數據只在最開始進來的時候進行加載,然后就保持住這個頁面的狀態了,並不會每次進來都進行數據的加載刷新了。

使用IndexedStack來保持頁面狀態的優點就是配置簡單,但是它也有很大的缺點:IndexedStack中管理的子頁面在一開始就全部一次性加載出來了,不管有沒有顯示出來,然后通過index屬性來確定到底顯示哪一個頁面。

第二種方式:AutomaticKeepAliveClientMixin

如果所有的頁面都需要保持頁面狀態,那么就使用indexdStack;如果有些頁面需要保持頁面狀態,有些頁面需要進來就刷新,那么我們就需要使用AutomaticKeepAliveMixin這個類來單獨控制某個頁面的狀態。

AutomaticKeepAliveClientMixin相比IndexdStack,配置起來要復雜一些。

AutomaticKeepAliveClientMixin結合底部BottomNavigationBar來保持頁面狀態的時候,其配置步驟如下:

import 'package:flutter/material.dart';
import 'package:flutter_jdshop/pages/tabs/CategoryPage.dart';
import 'package:flutter_jdshop/pages/tabs/HomePage.dart';
import 'package:flutter_jdshop/pages/tabs/ShoppingCartPage.dart';
import 'package:flutter_jdshop/pages/tabs/UserPage.dart';

class Tabs extends StatefulWidget {
  Tabs({Key key}) : super(key: key);

  _TabsState createState() => _TabsState();
}

class _TabsState extends State<Tabs> {

  int _currentIndex = 0;//記錄當前選中哪個頁面
  
  //第1步,聲明PageController
  PageController _pageController;

  @override
  void initState() { 
    super.initState();
    //第2步,初始化PageController
    this._pageController = PageController(initialPage: this._currentIndex);
  }

  List<Widget> _pages = [
    HomePage(),
    CategoryPage(),
    ShoppingCartPage(),
    UserPage()
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("JDShop")),
      //第3步,將body設置成PageView,並配置PageView的controller屬性
      body: PageView(
        controller: this._pageController,
        children: this._pages,
      ),
      bottomNavigationBar: BottomNavigationBar(
        fixedColor: Colors.red,//底部導航欄按鈕選中時的顏色
        type: BottomNavigationBarType.fixed,//底部導航欄的適配,當item多的時候都展示出來
        currentIndex: this._currentIndex,
        onTap: (index){
          setState(() {
            //第4步,設置點擊底部Tab的時候的頁面跳轉
            this._currentIndex = index;
            this._pageController.jumpToPage(this._currentIndex);
          });
        },
        items: [
          BottomNavigationBarItem(icon: Icon(Icons.home), title: Text("首頁")),
          BottomNavigationBarItem(icon: Icon(Icons.category), title: Text("分類")),
          BottomNavigationBarItem(icon: Icon(Icons.shopping_cart), title: Text("購物車")),
          BottomNavigationBarItem(icon: Icon(Icons.people), title: Text("我的"))
        ],
      ),
    );
  }
}

以上前4步都是在tabs.dart中進行配置的,此時所有的頁面還是不可保持頁面狀態的。然后第5步就是在需要保持頁面狀態的頁面里面混入AutomaticKeepAliveClientMixin類,並將wantKeepAlive方法返回為true,如下所示:

//首頁頁面
class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin{
  
  @override
  bool get wantKeepAlive => true;
  
  
  //分類頁面
  class _CategoryPageState extends State<CategoryPage> with AutomaticKeepAliveClientMixin{

  @override
  bool get wantKeepAlive => true;

這樣,首頁頁面和分類頁面就實現了頁面狀態的保持,頁面數據只在首次進入該頁面的時候進行刷新;而其他沒有實現頁面保持的頁面在每次進入該頁面的時候,數據都會刷新。

使用AutomaticKeepAliveClientMixin這個類來保持首頁和分類頁面狀態。

 

原文地址:https://cloud.tencent.com/developer/article/1507094

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM