美文网首页
BottomNavigationBar尝试 2023-08-16

BottomNavigationBar尝试 2023-08-16

作者: 勇往直前888 | 来源:发表于2023-08-17 10:03 被阅读0次

    简介

    工具类的首页,大多数都做成tab切换的样子。

    企业微信截图_5df05190-daaa-4098-a223-25d8d5e054a0.png

    实现方案

    • Scaffold框架有一个属性Widget? bottomNavigationBar,就是专门做这个的。

    • 方案1:类型是Widget?,其实不大准确;大多数时候,这里都会给一个BottomNavigationBar

    • 方案2:当然,约束条件松一点,可以自己用Container模仿一个,那么实现起来就更自由了。

    • 如果没有特殊的要求,直接使用BottomNavigationBar是最简单的。

    底部实现

    • BottomNavigationBar要结合BottomNavigationBarItem一起用,一个图标,一个文本,最常用的模式
    Scaffold(
          bottomNavigationBar: BottomNavigationBar(
            items: <BottomNavigationBarItem>[
              BottomNavigationBarItem(title: Text('首页'),icon: Icon(Icons.home)),
              BottomNavigationBarItem(title: Text('书籍'),icon: Icon(Icons.book)),
              BottomNavigationBarItem(title: Text('我的'),icon: Icon(Icons.perm_identity)),
            ],
          ),
        );
    
    • 选中,通过currentIndex属性设置当前选中的BottomNavigationBarItem;要注意的事这里只是底部按钮的选中状态,页面内容并不会变化。

    页面切换

    方案1:页面切换

    int _currentIndex = 0;
    
    Widget _currBody = HomePage();
    
    _onTap(int index) {
        switch (index) {
          case 0:
            _currBody = HomePage();;
            break;
          case 1:
            _currBody = BookPage();
            break;
          case 2:
            _currBody = MyPage();
            break;
        }
        setState(() {
          _currentIndex = index;
        });
      }
    
    Scaffold(
          body: _currBody,
          bottomNavigationBar: BottomNavigationBar(
            onTap: _onTap,
            type: BottomNavigationBarType.shifting,
            selectedItemColor: Theme.of(context).primaryColor,
            unselectedItemColor: Colors.black,
            currentIndex: _currentIndex,
            items: <BottomNavigationBarItem>[
              BottomNavigationBarItem(title: Text('首页'), icon: Icon(Icons.home)),
              BottomNavigationBarItem(title: Text('书籍'), icon: Icon(Icons.book)),
              BottomNavigationBarItem(
                  title: Text('我的'), icon: Icon(Icons.perm_identity)),
            ],
          ),
        );
    

    这个通过Switch语句,进行切换,问题是页面不断重建,不能保持状态
    Flutter Widgets 之 BottomNavigationBar

    方案2:数组

    import 'package:flutter/material.dart';
    import 'tabs/Category.dart';
    import 'tabs/Email.dart';
    import 'tabs/Home.dart';
    import 'tabs/Setting.dart';
    
    class Tabs extends StatefulWidget {
      const Tabs({Key? key}) : super(key: key);
    
      @override
      _TabsState createState() => _TabsState();
    }
    
    class _TabsState extends State<Tabs> {
      int currentIndex = 0;
      List _pageList = [HomePage(), CategoryPage(), SettingPage(), EmailPage()];
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(
              title: const Text('Flutter Demo'),
            ),
            body: _pageList[currentIndex],
            bottomNavigationBar: BottomNavigationBar(
              type: BottomNavigationBarType.fixed,
              currentIndex: currentIndex,
              onTap: (int index) {
                setState(() {
                  currentIndex = index;
                });
              },
              items: const [
                BottomNavigationBarItem(
                  icon: Icon(Icons.home),
                  label: "首页",
                ),
                BottomNavigationBarItem(
                    icon: Icon(Icons.category), title: Text("分类")),
                BottomNavigationBarItem(icon: Icon(Icons.mail), title: Text("邮件")),
                BottomNavigationBarItem(
                    icon: Icon(Icons.settings), title: Text("设置")),
              ],
            ),
          ),
          theme: ThemeData(
            primarySwatch: Colors.yellow,
          ),
        );
      }
    }
    

    这里把页面保存在一个数组中,避免了页面频繁重建,也能保持状态。
    Flutter BottomNavigationBar组件

    方案3:IndexedStack

    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]),
            ],
          ),
        );
      }
    }
    

    这个也用一个数组保存了页面,有缓存,能保持状态,并且封装成了组件,感觉是最匹配的。
    Flutter BottomNavigationBar 页面缓存

    小结

    • 如果能满足要求,直接使用BottomNavigationBar+IndexedStack的组合是最方便的;

    • 对于自定义,还是用Container()来模拟比较好

    相关文章

      网友评论

          本文标题:BottomNavigationBar尝试 2023-08-16

          本文链接:https://www.haomeiwen.com/subject/tdghmdtx.html