Flutter BottomNavigationBar 页面缓存

目录

问题描述

使用BottomNavigationBar实现页面的类似Android中Fragment切换的效果时,发现每次切换页面的时候,上个页面都会被销毁,新的页面都会重新创建,但是有时不需要重新创建,因此需要对页面进行缓存

解决方法

1.使用IndexedStack

IndexedStack可以同时创建多个Widget然后根据index展示对应的页面,关键代码如下:

class MainPage extends StatefulWidget {
  const MainPage({Key? key}) : super(key: key);

  @override
  State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
  var pages = [
    WeiChatPage(),
    DevicePage(),
    MinePage()
  ];
  var titles = ["首页","设备","我的"];
  var currentIndex = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leadingWidth: 70,
        leading: currentIndex == 1 ? TextButton(
          style: ButtonStyle(
            padding: MaterialStateProperty.all(EdgeInsets.only(left: 10)),
          ),
          onPressed: (){},
          child: Text("切换设备",style: TextStyle(
              color: Colors.black,
              fontSize: 14
          ),),
        ) : null,
        actions: currentIndex == 1 ? [
          IconButton(onPressed: (){}, icon: Icon(Icons.add,color: Colors.black,))
        ] : null,
        backgroundColor: Colors.white,
        elevation: 0.2,
        centerTitle: true,
        title: Text(titles[currentIndex],style: TextStyle(
          color: Colors.black
        ),),
      ),
      body: IndexedStack( /// 在这里修改
        index: currentIndex,
        children: pages,
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: currentIndex,
        type: BottomNavigationBarType.fixed,
        onTap: (index) {
          setState(() {
            currentIndex = index;
          });
        },
        items: [
          BottomNavigationBarItem(
              icon: Icon(Icons.messenger_outlined),
              label:titles[0]),
          BottomNavigationBarItem(
              icon: Icon(Icons.settings),
              label: titles[1]),
          BottomNavigationBarItem(
              icon: Icon(Icons.person),
              label: titles[2]),
        ],
      ),
    );
  }
}
2.使用PageView

使用PageView可实现只缓存某个页面,这里我使用了flukit库

dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  flukit: ^3.0.1 #工具类

然后将页面使用KeepAliveWrapper包裹,如下所示,这里我只包裹了WeiChatPage页面

class MainPage extends StatefulWidget {
  const MainPage({Key? key}) : super(key: key);

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  /// 初始化控制器
  late PageController pageController;
  var pages = [
    KeepAliveWrapper(child: WeiChatPage(),),
    DevicePage(),
    MinePage()
  ];
  var titles = ["首页","设备","我的"];
  var currentIndex = 0;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    //创建控制器的实例
    pageController = new PageController(
      //用来配置PageView中默认显示的页面 从0开始
      initialPage: 0,
      //为true是保持加载的每个页面的状态
      keepPage: true,
    );

  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leadingWidth: 70,
        leading: currentIndex == 1 ? TextButton(
          style: ButtonStyle(
            padding: MaterialStateProperty.all(EdgeInsets.only(left: 10)),
          ),
          onPressed: (){},
          child: Text("切换设备",style: TextStyle(
              color: Colors.black,
              fontSize: 14
          ),),
        ) : null,
        actions: currentIndex == 1 ? [
          IconButton(onPressed: (){}, icon: Icon(Icons.add,color: Colors.black,))
        ] : null,
        backgroundColor: Colors.white,
        elevation: 0.2,
        centerTitle: true,
        title: Text(titles[currentIndex],style: TextStyle(
          color: Colors.black
        ),),
      ),
      body: PageView( /// 在这里修改
        // index: currentIndex,
        /// 控制跳转翻页的控制器
        controller: pageController,
        //禁止滑动
        physics: const NeverScrollableScrollPhysics(),
        /// 页面滑动
        /// 这里设置 PageView 页面滑动也能
        onPageChanged: (index) {
          setState(() {
            // 更新当前的索引值
            currentIndex = index;
          });
        },
        children: pages,
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: currentIndex,
        type: BottomNavigationBarType.fixed,
        onTap: (index) {
          // 控制 PageView 跳转到指定的页面
          pageController.jumpToPage(index);
          setState(() {
            currentIndex = index;
          });
        },
        items: [
          BottomNavigationBarItem(
              icon: Icon(Icons.messenger_outlined),
              label:titles[0]),
          BottomNavigationBarItem(
              icon: Icon(Icons.settings),
              label: titles[1]),
          BottomNavigationBarItem(
              icon: Icon(Icons.person),
              label: titles[2]),
        ],
      ),
    );
  }
}

然后我们切换页面可以看看打印输出,其中WeiChatPage只创建了一次


©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容