如何在Flutter的BottomNavigationBar中心图标上方添加凹口?
可以实现你要的凹口效果,默认的BottomNavigationBar组件本身不支持直接添加这种凹口,不过我们可以通过Stack + 自定义裁剪背景的方式来实现,下面是具体的实现代码和思路:
实现思路
- 用
Stack组件将自定义的带凹口底部背景、透明化的BottomNavigationBar,以及悬浮的中心图标组合在一起 - 将BottomNavigationBar的中间项设为空白占位,避免和悬浮图标冲突
- 通过
CustomClipper绘制带凹口的底部背景,控制凹口的大小和深度
完整代码示例
替换你原来的BottomNavigationBar代码为以下实现:
return Stack( alignment: Alignment.bottomCenter, children: [ // 带凹口的底部背景容器 ClipPath( clipper: BottomNavNotchClipper(), child: Container( height: kBottomNavigationBarHeight, color: Colors.white, // 这里设置底部导航栏的背景色 ), ), // 透明化的底部导航栏 BottomNavigationBar( type: BottomNavigationBarType.fixed, fixedColor: Color(0xff2398C3), showSelectedLabels: false, showUnselectedLabels: false, currentIndex: snapshot.data.index, onTap: _bottomNavBarBloc.pickItem, backgroundColor: Colors.transparent, // 设为透明,显示下方的凹口背景 elevation: 0, // 移除导航栏阴影 items: [ BottomNavigationBarItem( label: 'Search', icon: Icon(Icons.search), ), BottomNavigationBarItem( label: 'Browse', icon: Icon(Icons.view_list), ), BottomNavigationBarItem( label: 'Icon', icon: SizedBox.shrink(), // 中间项设为空白占位 ), BottomNavigationBarItem( label: 'Favorites', icon: Icon(Icons.bookmark), ), BottomNavigationBarItem( label: 'Settings', icon: Icon(Icons.settings), ), ], ), // 悬浮在凹口处的中心图标 Positioned( bottom: kBottomNavigationBarHeight / 2 - 17.5, // 调整位置让图标居中悬浮 child: GestureDetector( onTap: () => _bottomNavBarBloc.pickItem(2), // 绑定导航栏中间项的点击事件 child: Container( child: FlutterLogo( size: 35.0, ), ), ), ), ], ); // 自定义裁剪器,用于绘制底部导航栏的凹口 class BottomNavNotchClipper extends CustomClipper<Path> { @override Path getClip(Size size) { final path = Path(); final notchWidth = 60.0; // 凹口的宽度 final notchDepth = 15.0; // 凹口的深度 // 从左下角开始绘制路径 path.moveTo(0, 0); // 绘制到凹口左侧位置 path.lineTo((size.width - notchWidth) / 2, 0); // 绘制凹口左半部分的弧线 path.quadraticBezierTo( (size.width - notchWidth) / 2, -notchDepth, size.width / 2, -notchDepth, ); // 绘制凹口右半部分的弧线 path.quadraticBezierTo( (size.width + notchWidth) / 2, -notchDepth, (size.width + notchWidth) / 2, 0, ); // 绘制到右下角,再闭合路径 path.lineTo(size.width, 0); path.lineTo(size.width, size.height); path.lineTo(0, size.height); path.close(); return path; } @override bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false; }
关键细节说明
- 你可以通过修改
BottomNavNotchClipper里的notchWidth和notchDepth参数,调整凹口的宽度和深度,匹配你的设计需求 - 悬浮图标的位置通过
Positioned的bottom属性调整,确保刚好卡在凹口处 - 将BottomNavigationBar的
backgroundColor设为透明、elevation设为0,是为了让下方的凹口背景完全显示出来
内容的提问来源于stack exchange,提问作者Md Shamim Hossain
相关产品推荐
相关产品推荐

