Flutter页面切换状态维持

在flutter中,使用类似于PageView进行页面切换时,如果不做处理,不会保持页面原状态。也就是从A页面切换到B页面,再从B页面切回到A页面,A页面显示都会重新加载。如果A页面加载比较耗时(例如有网络请求),就会带来不好的用户体验。如下图所示,页面已经加载过了,再次切换时还会重新加载。
在这里插入图片描述
最终,我们想要的效果是页面第一次加载会进行网络请求,当再次切换回到该页面时,希望维持原状态不变,效果如下图所示:
在这里插入图片描述

一、TabBar+TabBarView的页面切换状态维持

方法:使用AutomaticKeepAliveClientMixin
在TabBarView(也可以用PageView)每个子页面的State类实现AutomaticKeepAliveClientMixin接口,然后在子页面的State类重写wantKeepAlive为true即可。
注意点:State类build方法中要添加super.build(context);不然会出现某些页面切换没有维持原状态。
例如:

class PersonEventList extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _PersonEventListState();
  }
}
class _PersonEventListState extends State<PersonEventList>
    with AutomaticKeepAliveClientMixin {
  //导航栏切换时保持原有状态
  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext mContext) {
    super.build(context);
    return ......
    .............
}}

二、底部导航栏切换时维持原状态

Flutter中底部导航栏一般使用BottomAppBar或者BottomNavigationBar组件来实现,要想维持页面切换维持原状态,如下图所示,也要做一些处理:
在这里插入图片描述

2.1 使用IndexedStack

IndexedStack继承自Stack,它可以叠堆多个组件,并通过index来控制指定的组件显示。我们只需要用这个Widget将body中的子页面包裹就能达到目的。

class _HomeRouteState extends State<HomeRoute> {
   var _position = 0;
   List<Widget> _pageList = List();
    _pageList.add(RepoListRoute());
    _pageList.add(RepoHistoryPage());
    _pageList.add(TrendRoute());
    _pageList.add(PersonDetailPage());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: _buildBottomAppBar(),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      body: IndexedStack(
          index: _position,
          children: _pageList,
        ),
      ...........

2.2 使用Offstage实现

Offstage可容纳一个子组件,可更改其消失与否,当offstage属性为true时,子组件会消失。实现的原理与IndexedStack相同。

class _HomeRouteState extends State<HomeRoute> {
   var _position = 0;
   List<Widget> _pageList = List();
    _pageList.add(RepoListRoute());
    _pageList.add(RepoHistoryPage());
    _pageList.add(TrendRoute());
    _pageList.add(PersonDetailPage());

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      bottomNavigationBar: _buildBottomAppBar(),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      body:  Stack(
  children: [
    Offstage(
      offstage: _position != 0,
      child: _pageList[0],
    ),
    Offstage(
      offstage: _position != 1,
      child: _pageList[1],
    ),
    Offstage(
      offstage: _position != 2,
      child: _pageList[2],
    ),
  ],
),
      ...........

上面两种方式都能实现保持原页面状态,原理相同。但是,在第一次加载时,所有子页面都被实例化了,开销较大。所以可以采用下面第三种方式。

2.3 PageView + AutomaticKeepAliveClientMixin方式

body使用PageView来容纳所有子页面,在底部BottomAppBar的item点击时通过PageView的Controler实现页面切换,然后每个子页面继承AutomaticKeepAliveClientMixin即可。

三、项目介绍

以上例子在下面这个项目中都有体现:
项目地址:用flutter实现的一款界面精美的Github App
介绍:用Flutter实现的一款界面精美、功能较全、体验良好的Github客户端。支持多语言、换肤等功能。代码简单易懂且有充分的注释,很适用于学习Flutter。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值