阅读 310

Flutter 中 BottomNavigationBar 的使用详解 | Flutter Widgets

这是我参与更文挑战的第17天,活动详情查看: 更文挑战

前言

前面我们聊 PageView 的时候简单使用了一次 BottomNavigationBar ,今天我们详细聊聊他的使用以及一些优化处理。

先看效果

01.gif
上面这时今天要讲的所有效果的集合,下面我们讲分开详细聊聊怎么实现

基础的使用

与上个版本一样,我们一般使用是放在 Scaffold 中的 bottomNavigationBar 属性中的,用于展示在底部

整体页面和公共方法


/// BottomNavigationBar 页面
class BottomNavigationBarPage extends StatefulWidget {
  BottomNavigationBarPage({Key? key}) : super(key: key);

  @override
  _BottomNavigationBarPageState createState() =>
      _BottomNavigationBarPageState();
}

class _BottomNavigationBarPageState extends State<BottomNavigationBarPage> {
  // 当前子项索引
  int currentIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('PageView - ZeroFlutter'),
      ),
      body: [bodyWidget],
      // 底部导航栏
      bottomNavigationBar: [BottomNavigationBarWidget];
  }

  /// Tab 改变
  void onTabChanged(int value) {
    currentIndex = value;
    setState(() {});
  }
}
复制代码

底部导航栏

// 底部导航栏
BottomNavigationBar(
  // 当前页面索引
  currentIndex: currentIndex,
  // 导航子项集
  items: [
    // 导航子项
    BottomNavigationBarItem(
      // 图标
      icon: Icon(Icons.home),
      // 文字内容
      label: '首页',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.message_rounded),
      label: '消息',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.people),
      label: '我的',
    ),
  ],
  onTap: onTabChanged,
)
复制代码

这里我们就添加选中索引变化和 3 个子项集的功能

  • currentIndex 当前选中索引
  • items 子项集
    • BottomNavigationBarItem 子项
      • icon 图标(这里可以是任何 Widget)
      • label 文字

看看效果

02.gif

各种定制样式

这里有各种可以调节的参数来复原我们的设计图,其中要注意一下几点

  • selectedItemColorunselectedItemColor 搭配使用
    • 主要决定文字颜色
    • 没有 iconTheme.color 时,也决定 icon 颜色
    • fixedColor 不能与 selectedItemColor 同时使用
  • selectedIconThemeunselectedIconTheme 搭配使用
BottomNavigationBar(
  // 当前页面索引
  currentIndex: currentIndex,
  // 背景颜色
  backgroundColor: Colors.black,
  // 选中颜色
  selectedItemColor: Colors.orange,
  // 固定颜色
  // fixedColor:Colors.orange,
  // 未选中颜色
  unselectedItemColor: Colors.lightGreen,
  // 选中图标主题
  selectedIconTheme: IconThemeData(
    // 图标颜色
    color: Colors.red,
    // 图标大小
    size: 32,
    // 图标透明度
    opacity: 1.0,
  ),
  // 未选中图标主题
  unselectedIconTheme: IconThemeData(
    color: Colors.blue,
    size: 24,
    opacity: 0.5,
  ),
  items: [
    BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: '首页',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.message_rounded),
      label: '消息',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.people),
      label: '我的',
    ),
  ],
  onTap: onTabChanged,
)
复制代码

看效果

03.gif

统一文字大小

上面的效果选中和未选中切换时会有一个文字大小的变化,交互和 PM 说这个不好看,怎么办?

BottomNavigationBar(
  currentIndex: currentIndex,
  // 设置文字大小
  selectedFontSize: 14,
  unselectedFontSize: 14,
  items: [
    BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: '首页',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.message_rounded),
      label: '消息',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.people),
      label: '我的',
    ),
  ],
  onTap: onTabChanged,
)
复制代码

看一眼源码默认,如下,所以我们统一改为一个数值即可

  • selectedFontSize = 14
  • unselectedFontSize = 12

看效果

04.gif

选中才显示文字

看下面的效果虽然很少见,但是也是有 App 这样去做的,相对于颜色区分,这种效果区分选中也是非常棒的

BottomNavigationBar(
  currentIndex: currentIndex,
  // 显示选中的文字
  showSelectedLabels: true,
  // 显示不选中时的问题
  showUnselectedLabels: false,
  items: [
    BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: '首页',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.message_rounded),
      label: '消息',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.people),
      label: '我的',
    ),
  ],
  onTap: onTabChanged,
)
复制代码

看效果

05.gif

选中背景一起变颜色

我们这里设置一下 type: BottomNavigationBarType.shifting 其实默认情况下,当你 items 超过3个的时候会自动切换到这个类型上,也可以强制设置为 BottomNavigationBarType.fixed 不要这种效果

BottomNavigationBar(
  currentIndex: currentIndex,
  // 显示选中的文字
  type: BottomNavigationBarType.shifting,
  items: [
    BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: '首页',
      // 设置背景色
      backgroundColor: Colors.blue,
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.message_rounded),
      label: '消息',
      // 设置背景色
      backgroundColor: Colors.red,
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.people),
      label: '我的',
      // 设置背景色
      backgroundColor: Colors.orange,
    ),
  ],
  onTap: onTabChanged,
)
复制代码

这里我们就需要为每个 BottomNavigationBarItem 设置 backgroundColor 来切换颜色了

看效果

056gif.gif

去掉点击水波纹效果

交互和PM 又说了,这个水波纹效果不好看,怎么去掉呢?

// 去掉长按效果
Theme(
  data: ThemeData(
    // 去掉水波纹效果
    splashColor: Colors.transparent,
    // 去掉长按效果
    // highlightColor: Colors.transparent,
  ),
  child: BottomNavigationBar(
    // 当前页面索引
    currentIndex: currentIndex,
    selectedFontSize: 14,
    unselectedFontSize: 14,
    // 导航子项集
    items: [
      // 导航子项
      BottomNavigationBarItem(
        // 图标
        icon: Icon(Icons.home),
        // 文字内容
        label: '首页',
      ),
      BottomNavigationBarItem(
        icon: Icon(Icons.message_rounded),
        label: '消息',
      ),
      BottomNavigationBarItem(
        icon: Icon(Icons.people),
        label: '我的',
      ),
    ],
    onTap: onTabChanged,
  ),
)
复制代码

在 Flutter 中所有的控件都是Widget 包括主题设置也是一个 Widget ,所以这里我们只需要嵌套一个 Theme,然后设置水波纹属性为透明即可

看效果

07.gif

去掉长按提示语

image.png
像上面的提示语,一般是用不到的,需要去掉怎么办呢?

BottomNavigationBar(
  currentIndex: currentIndex,
  items: [
    BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: '首页',
      // 设置提示为空
      tooltip: '',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.message_rounded),
      label: '消息',
      tooltip: '',
    ),
    BottomNavigationBarItem(
      icon: Icon(Icons.people),
      label: '我的',
      tooltip: '',
    ),
  ],
  onTap: onTabChanged,
)
复制代码

这里只需要将 tooltip 设置为空即可

看效果

08.gif

自定义图标

为了展示我们自己 App 的品牌特色,每家的图标都有所不同,这里我们可以直接把 icon 设置为 Image 即可。

BottomNavigationBar(
  currentIndex: currentIndex,
  selectedItemColor: Colors.purple[800],
  items: [
    BottomNavigationBarItem(
      // 默认图标
      icon: getItemIcon('assets/icons/icon_home_unselect.png'),
      // 选中图标
      activeIcon: getItemIcon('assets/icons/icon_home.png'),
      label: '首页',
    ),
    BottomNavigationBarItem(
      icon: getItemIcon('assets/icons/icon_msg_unselect.png'),
      activeIcon: getItemIcon('assets/icons/icon_msg.png'),
      label: '消息',
    ),
    BottomNavigationBarItem(
      icon: getItemIcon('assets/icons/icon_me_unselect.png'),
      activeIcon: getItemIcon('assets/icons/icon_me.png'),
      label: '我的',
    ),
  ],
  onTap: onTabChanged,
)
复制代码
  • icon 未选中图标
  • activeIcon 选中图标

getItemIcon

/// 获取项目 icon
  Widget getItemIcon(String icon) {
    return Image.asset(
      icon,
      width: 24,
      height: 24,
    );
  }
复制代码

看效果

09.gif

源码仓库

基于 Flutter 🔥 最新版本

参考链接

关注专栏

  • 此文章已收录到下面👇 的专栏,可以直接关注
  • 更多文章继续阅读|系列文章持续更新

👏 欢迎点赞➕收藏➕关注,有任何问题随时在下面👇评论,我会第一时间回复哦

文章分类
Android
文章标签