📚 目录
简介
BottomNavigationBar 是 Flutter 中最常用的底部导航组件,通常与 Scaffold 配合使用,用于在应用的不同页面之间切换。
适用场景
- 主页面导航(3-5个主要功能)
- 社交应用(首页、消息、我的等)
- 电商应用(首页、分类、购物车、我的)
- 工具类应用的功能切换
特点
✅ 简单易用,Material Design 风格
✅ 支持图标和文字
✅ 自动处理选中状态
✅ 支持固定和移动两种模式
⚠️ 重要提示
必须包含 main() 函数
所有 Flutter 应用都必须有一个 main() 函数作为入口点,否则会出现以下错误:
Error: Undefined name 'main'.
if (entrypoint.main is _UnaryFunction) {
^^^^
正确的文件结构:
dart
import 'package:flutter/material.dart';
// 1. main() 函数 - 应用入口(必需)
void main() => runApp(MyApp());
// 2. MyApp 类 - 根组件(必需)
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: YourHomePage(), // 你的主页面
);
}
}
// 3. 你的页面组件
class YourHomePage extends StatefulWidget {
// ...
}
❌ 错误示例(缺少 main 函数):
dart
import 'package:flutter/material.dart';
// 直接写组件,没有 main() 函数
class MyHomePage extends StatefulWidget {
// ...
}
✅ 正确示例(完整结构):
dart
import 'package:flutter/material.dart';
void main() => runApp(const MyApp()); // 入口函数,使用 const
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key); // 添加 key 参数
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key); // 添加 key 参数
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// ...
}
关于 Key 参数
所有公共 Widget 的构造函数都应该有一个可选的 key 参数,这是 Flutter 的最佳实践:
dart
// ✅ 推荐写法
class MyWidget extends StatelessWidget {
const MyWidget({Key? key}) : super(key: key);
// ...
}
// ⚠️ 可以运行但不推荐
class MyWidget extends StatelessWidget {
// 缺少 key 参数
}
为什么需要 key 参数?
- 帮助 Flutter 识别和管理 Widget
- 在列表中保持 Widget 状态
- 提高性能和可维护性
基本用法
最简单的示例
dart
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _currentIndex = 0; // 当前选中的索引
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('底部导航栏示例'),
),
body: Center(
child: Text(
'当前页面: $_currentIndex',
style: const TextStyle(fontSize: 24),
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex, // 当前选中项
onTap: (index) {
setState(() {
_currentIndex = index; // 更新选中项
});
},
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: '首页',
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: '搜索',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: '我的',
),
],
),
);
}
}
核心属性
1. items(必需)
导航项列表,类型为 List<BottomNavigationBarItem>
dart
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home), // 图标
activeIcon: Icon(Icons.home), // 选中时的图标(可选)
label: '首页', // 文字标签
backgroundColor: Colors.blue, // 背景色(仅在 shifting 模式下有效)
tooltip: '首页', // 长按提示(可选)
),
]
2. currentIndex
当前选中项的索引,从 0 开始
dart
currentIndex: 0 // 默认选中第一项
3. onTap
点击事件回调
dart
onTap: (int index) {
print('点击了第 $index 项');
setState(() {
_currentIndex = index;
});
}
4. type
导航栏类型
dart
type: BottomNavigationBarType.fixed, // 固定模式(默认,3-5项时推荐)
type: BottomNavigationBarType.shifting, // 移动模式(4项以上时自动启用)
区别:
fixed: 所有项固定显示,宽度相等shifting: 选中项会放大,未选中项缩小
5. 颜色相关
dart
backgroundColor: Colors.white, // 背景色
selectedItemColor: Colors.blue, // 选中项颜色
unselectedItemColor: Colors.grey, // 未选中项颜色
6. 图标和文字大小
dart
selectedFontSize: 14.0, // 选中项文字大小
unselectedFontSize: 12.0, // 未选中项文字大小
iconSize: 24.0, // 图标大小
7. 显示标签
dart
showSelectedLabels: true, // 是否显示选中项的标签
showUnselectedLabels: true, // 是否显示未选中项的标签
8. 高度和边距
dart
elevation: 8.0, // 阴影高度
实战案例
案例1:完整的多页面导航
dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: MainPage(),
);
}
}
class MainPage extends StatefulWidget {
@override
_MainPageState createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
int _currentIndex = 0;
// 页面列表
final List<Widget> _pages = [
HomePage(),
CategoryPage(),
CartPage(),
ProfilePage(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: _pages[_currentIndex], // 根据索引显示不同页面
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
type: BottomNavigationBarType.fixed,
selectedItemColor: Colors.blue,
unselectedItemColor: Colors.grey,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: '首页',
),
BottomNavigationBarItem(
icon: Icon(Icons.category),
label: '分类',
),
BottomNavigationBarItem(
icon: Icon(Icons.shopping_cart),
label: '购物车',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: '我的',
),
],
),
);
}
}
// 首页
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('首页')),
body: Center(
child: Text('首页内容', style: TextStyle(fontSize: 24)),
),
);
}
}
// 分类页
class CategoryPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('分类')),
body: Center(
child: Text('分类内容', style: TextStyle(fontSize: 24)),
),
);
}
}
// 购物车页
class CartPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('购物车')),
body: Center(
child: Text('购物车内容', style: TextStyle(fontSize: 24)),
),
);
}
}
// 我的页面
class ProfilePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('我的')),
body: Center(
child: Text('个人中心', style: TextStyle(fontSize: 24)),
),
);
}
}
案例2:带徽章的导航栏(消息提示)
dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: BadgeBottomNavBar(),
);
}
}
class BadgeBottomNavBar extends StatefulWidget {
@override
_BadgeBottomNavBarState createState() => _BadgeBottomNavBarState();
}
class _BadgeBottomNavBarState extends State<BadgeBottomNavBar> {
int _currentIndex = 0;
int _messageCount = 5; // 消息数量
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('带徽章的导航栏')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('当前页面: $_currentIndex', style: TextStyle(fontSize: 24)),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
setState(() {
_messageCount++;
});
},
child: Text('增加消息数'),
),
],
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
setState(() {
_currentIndex = index;
if (index == 1) {
_messageCount = 0; // 点击消息页时清空徽章
}
});
},
type: BottomNavigationBarType.fixed,
selectedItemColor: Colors.blue,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: '首页',
),
BottomNavigationBarItem(
icon: _buildBadgeIcon(
Icons.message,
_messageCount,
),
label: '消息',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: '我的',
),
],
),
);
}
// 构建带徽章的图标
Widget _buildBadgeIcon(IconData icon, int count) {
return Stack(
children: [
Icon(icon),
if (count > 0)
Positioned(
right: 0,
top: 0,
child: Container(
padding: EdgeInsets.all(2),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(10),
),
constraints: BoxConstraints(
minWidth: 16,
minHeight: 16,
),
child: Text(
count > 99 ? '99+' : '$count',
style: TextStyle(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
),
],
);
}
}
案例3:自定义样式的导航栏
dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: CustomStyledNavBar(),
);
}
}
class CustomStyledNavBar extends StatefulWidget {
@override
_CustomStyledNavBarState createState() => _CustomStyledNavBarState();
}
class _CustomStyledNavBarState extends State<CustomStyledNavBar> {
int _currentIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('自定义样式导航栏'),
backgroundColor: Colors.deepPurple,
),
body: Center(
child: Text(
'当前页面: $_currentIndex',
style: TextStyle(fontSize: 24),
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
type: BottomNavigationBarType.fixed,
backgroundColor: Colors.deepPurple[50],
selectedItemColor: Colors.deepPurple,
unselectedItemColor: Colors.grey,
selectedFontSize: 14,
unselectedFontSize: 12,
iconSize: 28,
elevation: 10,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home_outlined),
activeIcon: Icon(Icons.home),
label: '首页',
),
BottomNavigationBarItem(
icon: Icon(Icons.explore_outlined),
activeIcon: Icon(Icons.explore),
label: '发现',
),
BottomNavigationBarItem(
icon: Icon(Icons.favorite_outline),
activeIcon: Icon(Icons.favorite),
label: '收藏',
),
BottomNavigationBarItem(
icon: Icon(Icons.person_outline),
activeIcon: Icon(Icons.person),
label: '我的',
),
],
),
);
}
}
案例4:Shifting 模式(移动模式)
dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: ShiftingNavBar(),
);
}
}
class ShiftingNavBar extends StatefulWidget {
@override
_ShiftingNavBarState createState() => _ShiftingNavBarState();
}
class _ShiftingNavBarState extends State<ShiftingNavBar> {
int _currentIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Shifting 模式')),
body: Center(
child: Text(
'当前页面: $_currentIndex',
style: TextStyle(fontSize: 24),
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
type: BottomNavigationBarType.shifting,
selectedItemColor: Colors.white,
unselectedItemColor: Colors.white70,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: '首页',
backgroundColor: Colors.blue,
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: '商务',
backgroundColor: Colors.green,
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: '学习',
backgroundColor: Colors.orange,
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: '设置',
backgroundColor: Colors.red,
),
],
),
);
}
}
案例5:只显示图标(隐藏文字)
dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: IconOnlyNavBar(),
);
}
}
class IconOnlyNavBar extends StatefulWidget {
@override
_IconOnlyNavBarState createState() => _IconOnlyNavBarState();
}
class _IconOnlyNavBarState extends State<IconOnlyNavBar> {
int _currentIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('只显示图标')),
body: Center(
child: Text(
'当前页面: $_currentIndex',
style: TextStyle(fontSize: 24),
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
type: BottomNavigationBarType.fixed,
selectedItemColor: Colors.blue,
unselectedItemColor: Colors.grey,
showSelectedLabels: false, // 隐藏选中项文字
showUnselectedLabels: false, // 隐藏未选中项文字
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home, size: 30),
label: '首页',
),
BottomNavigationBarItem(
icon: Icon(Icons.search, size: 30),
label: '搜索',
),
BottomNavigationBarItem(
icon: Icon(Icons.add_circle, size: 35),
label: '发布',
),
BottomNavigationBarItem(
icon: Icon(Icons.notifications, size: 30),
label: '通知',
),
BottomNavigationBarItem(
icon: Icon(Icons.person, size: 30),
label: '我的',
),
],
),
);
}
}
案例6:使用 PageView 实现滑动切换
dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: PageViewNavBar(),
);
}
}
class PageViewNavBar extends StatefulWidget {
@override
_PageViewNavBarState createState() => _PageViewNavBarState();
}
class _PageViewNavBarState extends State<PageViewNavBar> {
int _currentIndex = 0;
PageController _pageController = PageController();
@override
void dispose() {
_pageController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageView(
controller: _pageController,
onPageChanged: (index) {
setState(() {
_currentIndex = index;
});
},
children: [
_buildPage('首页', Colors.blue[100]!),
_buildPage('分类', Colors.green[100]!),
_buildPage('购物车', Colors.orange[100]!),
_buildPage('我的', Colors.purple[100]!),
],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
_pageController.animateToPage(
index,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
},
type: BottomNavigationBarType.fixed,
selectedItemColor: Colors.blue,
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'),
BottomNavigationBarItem(icon: Icon(Icons.category), label: '分类'),
BottomNavigationBarItem(icon: Icon(Icons.shopping_cart), label: '购物车'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: '我的'),
],
),
);
}
Widget _buildPage(String title, Color color) {
return Container(
color: color,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
title,
style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
),
SizedBox(height: 20),
Text(
'左右滑动可以切换页面',
style: TextStyle(fontSize: 16, color: Colors.grey[600]),
),
],
),
),
);
}
}
常见问题
0. ❌ Error: Undefined name 'main'
错误信息:
org-dartlang-app:/web_entrypoint.dart:21:22: Error: Undefined name 'main'.
if (entrypoint.main is _UnaryFunction) {
^^^^
原因: main.dart 文件中缺少 main() 函数
解决方案: 确保你的 main.dart 文件包含完整的结构
dart
import 'package:flutter/material.dart';
// ✅ 必须有 main() 函数
void main() => runApp(MyApp());
// ✅ 必须有 MaterialApp
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: YourHomePage(),
);
}
}
// 然后才是你的页面
class YourHomePage extends StatefulWidget {
@override
_YourHomePageState createState() => _YourHomePageState();
}
class _YourHomePageState extends State<YourHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
// ...
);
}
}
1. 为什么点击导航栏没有反应?
原因: 没有在 onTap 中调用 setState 更新 currentIndex
dart
// ❌ 错误写法
onTap: (index) {
_currentIndex = index; // 没有 setState
}
// ✅ 正确写法
onTap: (index) {
setState(() {
_currentIndex = index;
});
}
2. 如何实现中间凸起的按钮?
使用 FloatingActionButton 配合 floatingActionButtonLocation
dart
Scaffold(
body: _pages[_currentIndex],
floatingActionButton: FloatingActionButton(
onPressed: () {
// 处理中间按钮点击
},
child: Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomAppBar(
shape: CircularNotchedRectangle(), // 凹槽形状
notchMargin: 8.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
IconButton(icon: Icon(Icons.home), onPressed: () {}),
IconButton(icon: Icon(Icons.search), onPressed: () {}),
SizedBox(width: 40), // 中间留空
IconButton(icon: Icon(Icons.favorite), onPressed: () {}),
IconButton(icon: Icon(Icons.person), onPressed: () {}),
],
),
),
)
3. 如何保持页面状态不被销毁?
使用 AutomaticKeepAliveClientMixin
dart
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage>
with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => true; // 保持状态
@override
Widget build(BuildContext context) {
super.build(context); // 必须调用
return Scaffold(
appBar: AppBar(title: Text('首页')),
body: Center(child: Text('首页内容')),
);
}
}
4. 导航栏超过5项怎么办?
Material Design 建议最多5项,超过建议使用 Drawer(抽屉)或 TabBar
dart
// 如果确实需要更多项,可以设置 type
type: BottomNavigationBarType.shifting,
5. 如何自定义导航栏高度?
BottomNavigationBar 高度是固定的,如需自定义可使用 BottomAppBar
dart
bottomNavigationBar: BottomAppBar(
height: 80, // 自定义高度
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
// 自定义内容
],
),
)
最佳实践
1. 导航项数量建议
- 3-5项:最佳体验
- 少于3项:考虑使用 TabBar
- 多于5项:考虑使用 Drawer 或分组
2. 图标选择
- 使用语义清晰的图标
- 选中和未选中状态要有明显区别
- 建议使用 Material Icons
dart
// 推荐:使用 outlined 和 filled 版本
icon: Icon(Icons.home_outlined),
activeIcon: Icon(Icons.home),
3. 颜色搭配
- 选中颜色应与应用主题色一致
- 未选中颜色使用灰色系
- 背景色保持简洁
dart
selectedItemColor: Theme.of(context).primaryColor,
unselectedItemColor: Colors.grey[600],
backgroundColor: Colors.white,
4. 文字标签
- 简短明了(2-4个字)
- 避免使用长文本
- 可以根据需要隐藏未选中项的标签
dart
showSelectedLabels: true,
showUnselectedLabels: false, // 只显示选中项文字
5. 性能优化
- 使用
const构造函数 - 避免在
build方法中创建新的 List
dart
// ✅ 推荐:在类中定义
final List<Widget> _pages = const [
HomePage(),
CategoryPage(),
ProfilePage(),
];
// ❌ 不推荐:每次 build 都创建
@override
Widget build(BuildContext context) {
final pages = [HomePage(), CategoryPage()]; // 每次都创建新对象
}
6. 状态管理
对于复杂应用,建议使用状态管理方案(Provider、Riverpod、Bloc等)
dart
// 使用 Provider 示例
class NavigationProvider extends ChangeNotifier {
int _currentIndex = 0;
int get currentIndex => _currentIndex;
void setIndex(int index) {
_currentIndex = index;
notifyListeners();
}
}
完整示例:仿微信底部导航
dart
import 'package:flutter/material.dart';
void main() => runApp(WeChatApp());
class WeChatApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Color(0xFF07C160),
),
home: WeChatHome(),
);
}
}
class WeChatHome extends StatefulWidget {
@override
_WeChatHomeState createState() => _WeChatHomeState();
}
class _WeChatHomeState extends State<WeChatHome> {
int _currentIndex = 0;
int _messageCount = 3;
final List<Widget> _pages = [
ChatListPage(),
ContactsPage(),
DiscoverPage(),
ProfilePage(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: _currentIndex,
children: _pages,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentIndex,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
type: BottomNavigationBarType.fixed,
selectedItemColor: Color(0xFF07C160),
unselectedItemColor: Colors.grey,
selectedFontSize: 12,
unselectedFontSize: 12,
items: [
BottomNavigationBarItem(
icon: _buildBadgeIcon(Icons.chat_bubble_outline, _messageCount),
activeIcon: Icon(Icons.chat_bubble),
label: '微信',
),
BottomNavigationBarItem(
icon: Icon(Icons.contacts_outlined),
activeIcon: Icon(Icons.contacts),
label: '通讯录',
),
BottomNavigationBarItem(
icon: Icon(Icons.explore_outlined),
activeIcon: Icon(Icons.explore),
label: '发现',
),
BottomNavigationBarItem(
icon: Icon(Icons.person_outline),
activeIcon: Icon(Icons.person),
label: '我',
),
],
),
);
}
Widget _buildBadgeIcon(IconData icon, int count) {
return Stack(
clipBehavior: Clip.none,
children: [
Icon(icon),
if (count > 0)
Positioned(
right: -8,
top: -4,
child: Container(
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
constraints: BoxConstraints(minWidth: 18, minHeight: 18),
child: Text(
count > 99 ? '...' : '$count',
style: TextStyle(
color: Colors.white,
fontSize: 10,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
),
),
],
);
}
}
class ChatListPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('微信'),
backgroundColor: Color(0xFFEDEDED),
foregroundColor: Colors.black,
),
body: Center(child: Text('聊天列表', style: TextStyle(fontSize: 24))),
);
}
}
class ContactsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('通讯录'),
backgroundColor: Color(0xFFEDEDED),
foregroundColor: Colors.black,
),
body: Center(child: Text('通讯录', style: TextStyle(fontSize: 24))),
);
}
}
class DiscoverPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('发现'),
backgroundColor: Color(0xFFEDEDED),
foregroundColor: Colors.black,
),
body: Center(child: Text('发现', style: TextStyle(fontSize: 24))),
);
}
}
class ProfilePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('我'),
backgroundColor: Color(0xFFEDEDED),
foregroundColor: Colors.black,
),
body: Center(child: Text('个人中心', style: TextStyle(fontSize: 24))),
);
}
}
总结
BottomNavigationBar 是 Flutter 中最常用的导航组件之一,掌握它的使用对开发移动应用至关重要。
关键要点:
- 必须配合
StatefulWidget使用 - 通过
currentIndex和onTap控制选中状态 - 建议使用 3-5 个导航项
- 注意性能优化和状态保持
- 可以通过自定义实现更复杂的效果
希望这份文档能帮助你快速掌握 BottomNavigationBar 的使用!🎉