如何在Flutter中实现带中间弧形的BottomNavigationBar?
如何实现带有中间弧形的Flutter底部导航栏?
我目前用以下代码实现了顶部圆角的底部导航栏:
Container( decoration: const BoxDecoration( borderRadius: BorderRadius.only( topRight: Radius.circular(30), topLeft: Radius.circular(30)), boxShadow: [ BoxShadow(color: Colors.black38, spreadRadius: 0, blurRadius: 10), ], ), child: ClipRRect( borderRadius: const BorderRadius.only( topLeft: Radius.circular(30.0), topRight: Radius.circular(30.0), ), child: BottomNavigationBar( type: BottomNavigationBarType.fixed, backgroundColor: Colors.transparent, selectedItemColor: Colors.purple, unselectedItemColor: Colors.grey, currentIndex: widget.selectedIndex, onTap: widget.onTap, items: widget.items, ), ))
当前效果:
期望效果:
请问有没有方法实现这种中间带有弧形的底部导航栏?
可以通过Stack组件结合CustomPainter实现该效果,具体步骤如下:
1. 自定义弧形背景绘制类
创建继承自CustomPainter的类,绘制带顶部圆角和中间下凹弧形的背景:
class CurvedNavBarPainter extends CustomPainter { final Color color; final double curveRadius; CurvedNavBarPainter({required this.color, required this.curveRadius}); @override void paint(Canvas canvas, Size size) { Paint paint = Paint()..color = color; // 构建路径:顶部左右圆角 + 中间下凹弧形 Path path = Path() ..moveTo(0, curveRadius) ..quadraticBezierTo(0, 0, curveRadius, 0) // 左上角圆角 ..lineTo(size.width / 2 - curveRadius * 1.5, 0) ..quadraticBezierTo( size.width / 2, 0 - curveRadius, size.width / 2 + curveRadius * 1.5, 0) // 中间下凹弧形 ..lineTo(size.width - curveRadius, 0) ..quadraticBezierTo(size.width, 0, size.width, curveRadius) // 右上角圆角 ..lineTo(size.width, size.height) ..lineTo(0, size.height) ..close(); canvas.drawPath(path, paint); // 绘制阴影 Paint shadowPaint = Paint() ..color = Colors.black38 ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 10); canvas.drawPath(path, shadowPaint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; }
2. 组合Stack实现完整导航栏
用Stack叠加自定义背景和BottomNavigationBar,同时调整内边距避开弧形区域:
Stack( alignment: Alignment.bottomCenter, children: [ // 自定义弧形背景 CustomPaint( size: Size(MediaQuery.of(context).size.width, 80), painter: CurvedNavBarPainter( color: Colors.white, // 背景色 curveRadius: 30, // 弧形半径 ), ), // 底部导航栏 Padding( padding: const EdgeInsets.only(top: 15), // 顶部内边距避开弧形 child: BottomNavigationBar( type: BottomNavigationBarType.fixed, backgroundColor: Colors.transparent, elevation: 0, // 去掉默认阴影避免冲突 selectedItemColor: Colors.purple, unselectedItemColor: Colors.grey, currentIndex: widget.selectedIndex, onTap: widget.onTap, items: widget.items, ), ), ], )
关键说明
- 用
CustomPainter精确控制背景路径,比BorderRadius更灵活 - 设置
BottomNavigationBar的elevation: 0,避免默认阴影和自定义阴影冲突 - 顶部内边距可根据弧形半径调整,确保中间图标不被遮挡
内容的提问来源于stack exchange,提问作者Henni Kent
相关产品推荐
相关产品推荐

