Flutter 中 PageView 的使用详解 | Flutter Widgets
前言
上一篇我们聊了 IndexedStack 实现了一个简单的项目主页基础骨架的搭建,这一篇我们还是做这个主页骨架,但是是使用 PageView
来做并且附带了一些滑动效果。
看效果
先看看下面的效果一般是 App 的简单主页骨架,你知道使用 PageView
怎么实现的吗?这里相比上个
IndexedStack
版本有几个细节上的不同之处
- 页面可以滑动来切换
- 单独详情页可以改变状态并保持(count)
- 滑动页面时导航栏也是跟着变的
PageView(页面布局)
看名字就是知道他是专门来做页面布局使用的,这篇我们要一步一步实现上面的效果,如果你看过上篇的内容了,那么这篇会快就可以学会。
主体内容
上篇我们主体内容是添加 IndexedStack
,这篇我们改变成 PageView
即可,然后会新增一个控制器和页面滑动改变后的方法实现
/// PageView 页面
class PageViewPage extends StatefulWidget {
PageViewPage({Key? key}) : super(key: key);
@override
_PageViewPageState createState() => _PageViewPageState();
}
class _PageViewPageState extends State<PageViewPage> {
// 当前子项索引
int currentIndex = 0;
// 子项集
late List<Widget> children;
// 控制器
late PageController _controller;
@override
void initState() {
super.initState();
// 初始化子项集合
children = [
PageDetails(title: '首页'),
PageDetails(title: '消息'),
PageDetails(title: '我的'),
];
// 初始化控制器
_controller = PageController();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('PageView - ZeroFlutter'),
),
// 这里改为 PageView
body: PageView(
// 设置控制器
controller: _controller,
// 设置子项集
children: children,
// 添加页面滑动改变后,去改变索引变量刷新页面来更新底部导航
onPageChanged: (value) {
currentIndex = value;
setState(() {});
},
),
// 底部导航栏
bottomNavigationBar: [...],
);
}
}
子项页面内容
这里因为我们的页面内容肯定不是一成不变的,所以这篇我们将 PageDetails
继承自 StatefulWidget
,然后添加了 count
变量用于设置点击的次数。
/// 页面详情
class PageDetails extends StatefulWidget {
PageDetails({Key? key, required this.title}) : super(key: key);
final String title;
@override
_PageDetailsState createState() => _PageDetailsState();
}
class _PageDetailsState extends State<PageDetails> {
int count = 0;
@override
Widget build(BuildContext context) {
// 这里的打印可以记录一下,后面会用到
print('PageDetails build title:${widget.title}');
return Scaffold(
body: GestureDetector(
onTap: () {
count += 1;
setState(() {});
},
child: Center(
child: Text('${widget.title} count:$count'),
),
),
);
}
}
底部导航
这里的底部导航当点击时,我们增加了一个控制器跳转页面的操作。
BottomNavigationBar(
// 当前页面索引
currentIndex: currentIndex,
// 导航子项集
items: [
// 导航子项
BottomNavigationBarItem(
// 图标
icon: Icon(Icons.home),
// 文字内容
label: '首页',
),
BottomNavigationBarItem(
icon: Icon(Icons.message_rounded),
label: '消息',
),
BottomNavigationBarItem(
icon: Icon(Icons.people),
label: '我的',
),
],
onTap: (value) {
// 点击事件,用于改变当前索引,然后刷新
currentIndex = value;
setState(() {});
// 通过控制器实现跳转页面
_controller.jumpToPage(currentIndex);
},
)
运行效果
这样我们基础骨架就实现完毕,看下面的效果
优化页面
细心的你会发现上图页面计数器在页面切换后又归零了,我们实际项目肯定是页面继续保持上次的状态,下面看看怎么优化吧。
保持页面状态
Flutter 早就为我们考虑好了这种情况,真正当我们遇到的时候才会去搜索学习。
/// 页面详情
class PageDetails extends StatefulWidget {
PageDetails({Key? key, required this.title}) : super(key: key);
final String title;
@override
_PageDetailsState createState() => _PageDetailsState();
}
/// 这里混入了 AutomaticKeepAliveClientMixin
class _PageDetailsState extends State<PageDetails>
with AutomaticKeepAliveClientMixin {
int count = 0;
@override
Widget build(BuildContext context) {
super.build(context);
// 这里的打印可以记录一下,后面会用到
print('PageDetails build title:${widget.title}');
return Scaffold(
body: GestureDetector(
onTap: () {
count += 1;
setState(() {});
},
child: Center(
child: Text('${widget.title} count:$count'),
),
),
);
}
// 设置 true 期望保持页面状态
@override
bool get wantKeepAlive => true;
}
- 我们先看
9~11
行,with(混入)了一个AutomaticKeepAliveClientMixin
的mixin
类 - 第
31~32
行,覆写了get wantKeepAlive
方法,返回true
来保持页面状态
看看现在的效果
到这里我们就实现带有切换效果的项目页面主骨架啦,如果觉得有帮助到你记得点击关注哦
源码仓库
基于 Flutter 🔥 最新版本
参考链接
关注专栏
- 此文章已收录到下面👇 的专栏,可以直接关注
- 更多文章继续阅读|系列文章持续更新
👏 欢迎点赞➕收藏➕关注,有任何问题随时在下面👇评论,我会第一时间回复哦
转载自:https://juejin.cn/post/6973973088065028133