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,
            // 第二个需要设置的值:需要展示的所有页面的数组,需要注意的是,数组必须声明是<Widget>类型
            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.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;
 },

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

onTap: (index){
	setState(() {
	//页面控制器进行跳转 
	_pageController.jumpToPage(this._currentIndex);
	}); 
},

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; 
}

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: "我的")
            ],
          )
    );
  } 
}

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

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值