求助:在Flutter中实现特定样式的自定义底部导航栏
Flutter 实现带凸起中间按钮的底部导航栏
下面是实现你需要的底部导航栏的方案,完全基于Flutter原生组件,无需第三方包:
核心思路
- 用
BottomAppBar作为底部导航栏主体,通过shape属性设置中间圆形缺口,适配凸起的主按钮 - 搭配
FloatingActionButton作为中间凸起按钮,通过floatingActionButtonLocation定位到缺口位置 - 自定义导航项的选中/未选中样式,匹配设计需求
完整代码示例
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( title: 'Bottom Nav Demo', theme: ThemeData(primarySwatch: Colors.blue), home: const BottomNavScreen(), ); } } class BottomNavScreen extends StatefulWidget { const BottomNavScreen({super.key}); @override State<BottomNavScreen> createState() => _BottomNavScreenState(); } class _BottomNavScreenState extends State<BottomNavScreen> { // 当前选中的导航索引 int _selectedIndex = 0; // 导航项数据:图标、文字(除中间按钮外) final List<Map<String, dynamic>> _navItems = [ {'icon': Icons.home, 'label': '首页'}, {'icon': Icons.search, 'label': '搜索'}, {'icon': Icons.notifications, 'label': '通知'}, {'icon': Icons.person, 'label': '我的'}, ]; // 切换导航项 void _onItemTapped(int index) { setState(() { _selectedIndex = index; }); } // 中间按钮点击事件 void _onCenterButtonPressed() { // 这里添加中间按钮的业务逻辑 debugPrint('中间按钮被点击'); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('底部导航示例')), body: Center( child: Text('当前页面:${_navItems[_selectedIndex]['label']}'), ), // 中间凸起的主按钮 floatingActionButton: FloatingActionButton( onPressed: _onCenterButtonPressed, backgroundColor: Colors.orange, child: const Icon(Icons.add, color: Colors.white), elevation: 4, ), // 设置按钮位置,卡在BottomAppBar的缺口里 floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked, // 底部导航栏主体 bottomNavigationBar: BottomAppBar( shape: const CircularNotchedRectangle(), // 中间圆形缺口 color: Colors.white, elevation: 8, child: SizedBox( height: 60, child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ // 左侧两个导航项 _buildNavItem(0), _buildNavItem(1), // 中间留空,给FloatingActionButton const SizedBox(width: 40), // 右侧两个导航项 _buildNavItem(2), _buildNavItem(3), ], ), ), ), ); } // 构建单个导航项 Widget _buildNavItem(int index) { final isSelected = _selectedIndex == index; return InkWell( onTap: () => _onItemTapped(index), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( _navItems[index]['icon'], color: isSelected ? Colors.orange : Colors.grey, size: 24, ), const SizedBox(height: 4), Text( _navItems[index]['label'], style: TextStyle( color: isSelected ? Colors.orange : Colors.grey, fontSize: 12, fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, ), ), ], ), ); } }
自定义调整说明
- 修改中间按钮样式:直接调整
FloatingActionButton的backgroundColor、child、elevation等属性 - 调整导航项样式:修改
_buildNavItem里的颜色、文字大小、字体粗细参数 - 调整导航栏高度:修改
SizedBox(height: 60)的数值 - 自定义缺口形状:可以自定义
NotchedShape替换CircularNotchedRectangle()
内容的提问来源于stack exchange,提问作者Emmanuel Nartey
相关产品推荐
相关产品推荐

