Flutter中如何为单个BottomNavigationBarItem标签设置独特颜色
问题描述
我在Flutter应用中使用BottomNavigationBar,共有三个导航项。希望其中两个项(Home、Reminder)的标签使用默认的选中/未选中颜色,但第二个名为“Create”的项的标签无论选中与否都显示红色。现有代码如下:
import 'package:flutter/material.dart'; import 'package:playticket/screens/01.dart'; class CustomNavBar extends StatefulWidget { CustomNavBar({Key? key}) : super(key: key); @override State<CustomNavBar> createState() => _CustomNavBarState(); } class _CustomNavBarState extends State<CustomNavBar> { int _currentIndex = 0; @override Widget build(BuildContext context) { List<Widget> _screens = [ Screen1(), Screen1(), Screen1(), ]; return Scaffold( body: _screens[_currentIndex], bottomNavigationBar: SizedBox( height: 90, child: BottomNavigationBar( backgroundColor: Colors.white, type: BottomNavigationBarType.fixed, selectedLabelStyle: TextStyle(fontSize: 12, fontFamily: "Poppins", fontWeight: FontWeight.w600), unselectedLabelStyle: TextStyle(fontSize: 12, fontFamily: "Poppins", fontWeight: FontWeight.w600), unselectedItemColor: Color(0xff909090), currentIndex: _currentIndex, selectedItemColor: Color(0xff3D3D3D), onTap: (value) { setState(() => _currentIndex = value); }, items: [ BottomNavigationBarItem( activeIcon: ImageIcon(AssetImage("assets/images/home-icon.png"), size: 25,), label: "Home", icon: ImageIcon(AssetImage("assets/images/home-icon.png"), size: 25, color: Color(0xff909090),), ), BottomNavigationBarItem( icon: Image.asset("assets/images/add-box-fill.png", width: 28, height: 28,), label: "Create", ), BottomNavigationBarItem( activeIcon: ImageIcon(AssetImage("assets/images/ticket-icon.png"), size: 25, color: Color(0xff3D3D3D),), label: "Reminder", icon: ImageIcon(AssetImage("assets/images/ticket-icon.png"), size: 25, color: Color(0xff909090),) ), ], ), ), ); } }
解决方案
利用Flutter 3.3+新增的labelWidget属性,我们可以为每个导航项单独自定义标签样式,完美实现单个标签固定颜色的需求。修改步骤如下:
- 移除
BottomNavigationBar上全局的selectedLabelStyle和unselectedLabelStyle,避免全局样式干扰自定义标签 - 对Home、Reminder项,通过
labelWidget根据当前选中状态设置对应颜色 - 对Create项,直接固定标签文本颜色为红色,不受选中状态影响
修改后的完整代码:
import 'package:flutter/material.dart'; import 'package:playticket/screens/01.dart'; class CustomNavBar extends StatefulWidget { CustomNavBar({Key? key}) : super(key: key); @override State<CustomNavBar> createState() => _CustomNavBarState(); } class _CustomNavBarState extends State<CustomNavBar> { int _currentIndex = 0; // 提取通用样式,避免重复代码 final _labelTextStyle = const TextStyle( fontSize: 12, fontFamily: "Poppins", fontWeight: FontWeight.w600, ); final _selectedColor = const Color(0xff3D3D3D); final _unselectedColor = const Color(0xff909090); @override Widget build(BuildContext context) { List<Widget> _screens = [ Screen1(), Screen1(), Screen1(), ]; return Scaffold( body: _screens[_currentIndex], bottomNavigationBar: SizedBox( height: 90, child: BottomNavigationBar( backgroundColor: Colors.white, type: BottomNavigationBarType.fixed, // 移除全局标签样式 unselectedItemColor: _unselectedColor, currentIndex: _currentIndex, selectedItemColor: _selectedColor, onTap: (value) { setState(() => _currentIndex = value); }, items: [ BottomNavigationBarItem( activeIcon: const ImageIcon(AssetImage("assets/images/home-icon.png"), size: 25,), // 自定义Home标签样式,根据选中状态切换颜色 labelWidget: Text( "Home", style: _labelTextStyle.copyWith( color: _currentIndex == 0 ? _selectedColor : _unselectedColor, ), ), icon: const ImageIcon(AssetImage("assets/images/home-icon.png"), size: 25, color: Color(0xff909090),), ), BottomNavigationBarItem( icon: const Image.asset("assets/images/add-box-fill.png", width: 28, height: 28,), // Create标签固定红色 labelWidget: Text( "Create", style: _labelTextStyle.copyWith(color: Colors.red), ), ), BottomNavigationBarItem( activeIcon: const ImageIcon(AssetImage("assets/images/ticket-icon.png"), size: 25, color: Color(0xff3D3D3D),), // 自定义Reminder标签样式,根据选中状态切换颜色 labelWidget: Text( "Reminder", style: _labelTextStyle.copyWith( color: _currentIndex == 2 ? _selectedColor : _unselectedColor, ), ), icon: const ImageIcon(AssetImage("assets/images/ticket-icon.png"), size: 25, color: Color(0xff909090),) ), ], ), ), ); } }
关键说明
- 使用
labelWidget替代原有的label属性,完全掌控标签的样式 - 提取通用的文本样式到变量中,减少代码冗余,方便后续统一修改
- Create项的文本颜色直接固定为
Colors.red,无论当前是否选中都保持红色 - Home和Reminder项通过
_currentIndex判断选中状态,切换对应颜色,保持原有需求的默认颜色逻辑
内容的提问来源于stack exchange,提问作者Umer Yaseen
相关产品推荐
相关产品推荐

