• flutter_学习记录_02底部 Tab 切换保持页面状态的几种方法


    一、IndexedStack 保持页面状态

    1.1 IndexedStack原理说明

    IndexedStack 和 Stack 一样,都是层布局控件, 可以在一个控件上面放置另一 个控件,但唯一不同的是 IndexedStack 在同一时刻只能显示子控件中的一个控 件,通过 Index 属性来设置显示的控件。
    IndexedStack 来保持页面状态的优点就是配置简单。IndexedStack 保持页面状 态的缺点就是不方便单独控制每个页面的状态。

    1.2 IndexedStack 结合tab用法示例

    
    import 'package:fang_jd/Pages/Category.dart';
    import 'package:fang_jd/Pages/Home.dart';
    import 'package:fang_jd/Pages/Shop.dart';
    import 'package:fang_jd/Pages/User.dart';
    import 'package:flutter/material.dart'; 
    
    class Tabs extends StatefulWidget {
      const Tabs({super.key});
    
      
      State<Tabs> createState() => _TabsState();
    }
    
    class _TabsState extends State<Tabs> {
      late int  _currentIndex = 0;
      final List<Widget> _pageList = const [
      	// 需要替换成自己的页面
        HomePage(), 
        // 需要替换成自己的页面 
        CategoryPage(),
        // 需要替换成自己的页面
        ShopPage(),
        // 需要替换成自己的页面
        UserPage()
      ];
      
      Widget build(BuildContext context) {
        return  Scaffold(
              appBar: AppBar(
                title: const Text("JD shop"),
              ),
              //  用IndexedStack实现页面保活
              body: IndexedStack(
              	// 第一个需要设置的值:要展示哪个页面
                index: _currentIndex,
                // 第二个需要设置的值:需要展示的所有页面的数组,需要注意的是,数组必须声明是类型
                children: _pageList,
              ) ,
              bottomNavigationBar: BottomNavigationBar(
                currentIndex: _currentIndex,
                onTap: (index)  {
                  setState(() {
                    _currentIndex = index;
                  });
                } ,
                type: BottomNavigationBarType.fixed, // 当tab的个数比较多时,必须配置这个值才能显示出来
                selectedItemColor: Colors.red,
                items: const [
                    BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页1"),
                    BottomNavigationBarItem(icon: Icon(Icons.category), label: "分类"),
                    BottomNavigationBarItem(icon: Icon(Icons.shop), label: "购物车"),
                    BottomNavigationBarItem(icon: Icon(Icons.people), label: "我的")
                ],
              )
        );
      } 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    1.3 IndexedStack的缺点

    因为是用数组一次性加载页面的,所以一启动的时候,会把tab下所有的主页面都同时加载出来,增加启动时的负担。例如,刚启动的时候,只需要加载“首页”的数据,但是它会把“分类”、“购物车”、“我的”页面的数据也加载出来。

    二、AutomaticKeepAliveClientMixin 保持页面状态

    2.1 AutomaticKeepAliveClientMixin原理说明

    AutomaticKeepAliveClientMixin 结合 tab 切换保持页面状态相比 IndexedStack 而言配置起来稍 微有些复杂。它结合底部 BottomNavigationBar 保持页面状态的时候需要进行如下配置。
    主要步骤如下:
    1、添加一个变量:var _pageController;
    2、 在tab上的初始化方法,创建页面控制器 _pageController = PageController(initialPage : _currentIndex);
    3. 在body上,必须使用PageView组件加载不同的页面

    //必须用 PageView 加载不同的页面 
    body: PageView(
    	controller: _pageController, 
    	children: this._pageList, onPageChanged: (index){
    		_currentIndex = index;
     },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4、tab 点击的时候,用页面控制器进行跳转, _pageController.jumpToPage(this._currentIndex);

    onTap: (index){
    	setState(() {
    	//页面控制器进行跳转 
    	_pageController.jumpToPage(this._currentIndex);
    	}); 
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    5、需要持久化的页面加入如下代码:
    5.1 让页面继承“AutomaticKeepAliveClientMixin”
    5.2 重写wantKeepAlive的方法,返回值为true

    class HomePage extends StatefulWidget { 
    HomePage({Key key}) : super(key: key);
    _HomePageState createState() => _HomePageState(); 
    }
    
    class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin{
    
    bool get wantKeepAlive => true; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.2 代码示例

    tab的设置

    
    import 'package:fang_jd/Pages/Category.dart';
    import 'package:fang_jd/Pages/Home.dart';
    import 'package:fang_jd/Pages/Shop.dart';
    import 'package:fang_jd/Pages/User.dart';
    import 'package:flutter/material.dart'; 
    
    class Tabs extends StatefulWidget {
      const Tabs({super.key});
    
      
      State<Tabs> createState() => _TabsState();
    }
    
    class _TabsState extends State<Tabs> {
      late int  _currentIndex = 0;
      final List<Widget> _pageList = const [
        HomePage(),
        CategoryPage(),
        ShopPage(),
        UserPage()
      ];
      // 添加一个 pageController 
      late PageController _pageController;
    
      
      void initState() {
        // 在初始化的方法里,初始化_pageController
        _pageController = PageController(initialPage: _currentIndex);
        super.initState();
      }
    
      
      Widget build(BuildContext context) {
        return  Scaffold(
              appBar: AppBar(
                title: const Text("JD shop"),
              ),
              // body 中,必须用pageView来包裹
              body: PageView(
                // 第一个需要设置的属性:controller, 用于控制加载页面
                controller: _pageController,
                // 第二个需要设置的属性:需要加载哪些页面
                children: _pageList,
              ) , 
              bottomNavigationBar: BottomNavigationBar(
                currentIndex: _currentIndex,
                onTap: (index)  {
                  setState(() {
                    _currentIndex = index;
                    _pageController.jumpToPage(_currentIndex);
                  });
                } ,
                type: BottomNavigationBarType.fixed, // 当tab的个数比较多时,必须配置这个值才能显示出来
                selectedItemColor: Colors.red,
                items: const [
                    BottomNavigationBarItem(icon: Icon(Icons.home), label: "首页1"),
                    BottomNavigationBarItem(icon: Icon(Icons.category), label: "分类"),
                    BottomNavigationBarItem(icon: Icon(Icons.shop), label: "购物车"),
                    BottomNavigationBarItem(icon: Icon(Icons.people), label: "我的")
                ],
              )
        );
      } 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    在需要保活的页面的代码设置

    class HomePage extends StatefulWidget {
      const HomePage({super.key});
    
      
      State<HomePage> createState() => _HomePageState();
    }
    
    // 用with 关键字来继承 “AutomaticKeepAliveClientMixin”
    class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin {
     // 必须重写 “AutomaticKeepAliveClientMixin”的方法:wantKeepAlive
      
      bool get wantKeepAlive => true;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    P1825 [USACO11OPEN]Corn Maze S——bfs
    【教程】遥感数据与作物模型同化实践
    C语言第三十六弹---文件操作(中)
    WGBS项目文章 | 在缺氮情况下,细胞自噬对植物DNA甲基化会产生怎样的影响?
    《动手学深度学习 Pytorch版》 9.2 长短期记忆网络(LSTM)
    JMeter + Ant + Jenkins持续集成-接口自动化测试
    五年!!专科学历让我懂得了互联网
    Java 超经典面试题
    C 标准库 - <errno.h>和<float.h>详解
    四级单词大全h-n
  • 原文地址:https://blog.csdn.net/lyz0925/article/details/130909745