Flutter中如何为Bottom Navigation Bar的每个项添加背景色?
实现带独立背景色的底部导航栏
下面分别给出Flutter和Android原生的实现方案,还原你需要的每个导航项带独立背景色的效果:
Flutter 实现方案
通过自定义底部导航栏布局,为每个导航项配置独立背景色,代码如下:
import 'package:flutter/material.dart'; void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: const BottomNavWithColoredItems(), ); } } class BottomNavWithColoredItems extends StatefulWidget { const BottomNavWithColoredItems({super.key}); @override State<BottomNavWithColoredItems> createState() => _BottomNavWithColoredItemsState(); } class _BottomNavWithColoredItemsState extends State<BottomNavWithColoredItems> { int _selectedIndex = 0; // 导航项配置:图标、标题、背景色、文字颜色 final List<Map<String, dynamic>> _navItems = [ { 'icon': Icons.home, 'title': '首页', 'bgColor': const Color(0xFF6366F1), 'selectedColor': Colors.white, 'unselectedColor': Colors.grey.shade700, }, { 'icon': Icons.search, 'title': '搜索', 'bgColor': const Color(0xFFEC4899), 'selectedColor': Colors.white, 'unselectedColor': Colors.grey.shade700, }, { 'icon': Icons.add_circle, 'title': '发布', 'bgColor': const Color(0xFF10B981), 'selectedColor': Colors.white, 'unselectedColor': Colors.grey.shade700, }, { 'icon': Icons.notifications, 'title': '通知', 'bgColor': const Color(0xFFF59E0B), 'selectedColor': Colors.white, 'unselectedColor': Colors.grey.shade700, }, { 'icon': Icons.person, 'title': '我的', 'bgColor': const Color(0xFF8B5CF6), 'selectedColor': Colors.white, 'unselectedColor': Colors.grey.shade700, }, ]; void _onItemTapped(int index) { setState(() { _selectedIndex = index; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('带独立背景色的底部导航')), body: Center(child: Text('当前选中第${_selectedIndex+1}项')), bottomNavigationBar: Container( height: 60, padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: List.generate(_navItems.length, (index) { final item = _navItems[index]; final isSelected = _selectedIndex == index; return GestureDetector( onTap: () => _onItemTapped(index), child: Container( width: 60, decoration: BoxDecoration( color: isSelected ? item['bgColor'] : Colors.transparent, borderRadius: BorderRadius.circular(12), ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( item['icon'], color: isSelected ? item['selectedColor'] : item['unselectedColor'], size: 24, ), if (isSelected) Text( item['title'], style: TextStyle( color: item['selectedColor'], fontSize: 10, ), ), ], ), ), ); }), ), ), ); } }
实现说明
- 用
_navItems统一管理所有导航项的配置,方便修改颜色、图标和标题 - 选中导航项时显示对应背景色,同时显示标题;未选中时透明背景,仅显示图标
- 通过
GestureDetector处理点击事件,更新选中状态
Android 原生实现方案
通过自定义导航项布局+动态设置样式来实现效果:
1. 自定义导航项布局(res/layout/bottom_nav_item.xml)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:padding="8dp"> <ImageView android:id="@+id/icon" android:layout_width="24dp" android:layout_height="24dp" /> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:fontFamily="sans-serif-medium" android:textSize="10sp" android:visibility="gone" /> </LinearLayout>
2. Activity 代码实现
import android.graphics.Color import android.os.Bundle import android.view.MenuItem import android.view.View import android.widget.ImageView import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import com.google.android.material.bottomnavigation.BottomNavigationView class MainActivity : AppCompatActivity() { private lateinit var bottomNav: BottomNavigationView // 导航项背景色数组 private val navItemColors = listOf( Color.parseColor("#6366F1"), Color.parseColor("#EC4899"), Color.parseColor("#10B981"), Color.parseColor("#F59E0B"), Color.parseColor("#8B5CF6") ) // 图标资源ID private val iconIds = listOf( R.drawable.ic_home, R.drawable.ic_search, R.drawable.ic_add, R.drawable.ic_notification, R.drawable.ic_profile ) // 导航标题文字 private val titleTexts = listOf("首页", "搜索", "发布", "通知", "我的") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) bottomNav = findViewById(R.id.bottom_nav) setupBottomNav() } private fun setupBottomNav() { bottomNav.menu.clear() // 动态添加导航项 for (i in navItemColors.indices) { val menuItem = bottomNav.menu.add(0, i, i, titleTexts[i]) menuItem.icon = ContextCompat.getDrawable(this, iconIds[i]) } // 设置选中监听 bottomNav.setOnItemSelectedListener { menuItem -> updateNavItems(menuItem.itemId) true } // 默认选中第一项 updateNavItems(0) } private fun updateNavItems(selectedIndex: Int) { // 遍历所有导航项,更新样式 for (i in 0 until bottomNav.menu.size()) { val menuItem = bottomNav.menu.getItem(i) val itemView = bottomNav.findViewById<View>(menuItem.itemId) val icon = itemView.findViewById<ImageView>(R.id.icon) val title = itemView.findViewById<TextView>(R.id.title) if (i == selectedIndex) { // 选中状态:设置背景色、白色图标和文字 itemView.setBackgroundColor(navItemColors[i]) icon.setColorFilter(Color.WHITE) title.text = titleTexts[i] title.visibility = View.VISIBLE title.setTextColor(Color.WHITE) } else { // 未选中状态:透明背景、灰色图标、隐藏文字 itemView.setBackgroundColor(Color.TRANSPARENT) icon.setColorFilter(Color.GRAY) title.visibility = View.GONE } } } }
实现说明
- 自定义导航项布局,灵活控制图标和标题的显示
- 动态添加导航项,通过数组统一管理每个项的颜色、图标和文字
- 选中时切换背景色并显示标题,未选中时恢复默认样式
内容的提问来源于stack exchange,提问作者Ashirwad Kumar
相关产品推荐
相关产品推荐

