IndexedStack 和 Stack 一样,都是层布局控件, 可以在一个控件上面放置另一 个控件,但唯一不同的是 IndexedStack 在同一时刻只能显示子控件中的一个控 件,通过 Index 属性来设置显示的控件。
IndexedStack 来保持页面状态的优点就是配置简单。IndexedStack 保持页面状 态的缺点就是不方便单独控制每个页面的状态。
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: "我的")
],
)
);
}
}
因为是用数组一次性加载页面的,所以一启动的时候,会把tab下所有的主页面都同时加载出来,增加启动时的负担。例如,刚启动的时候,只需要加载“首页”的数据,但是它会把“分类”、“购物车”、“我的”页面的数据也加载出来。
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;
}
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;
}