求助:如何在Flutter中实现带底部凹形的容器设计
Flutter实现底部凹形容器方案
方法一:使用ClipPath自定义裁剪
通过自定义CustomClipper裁剪容器底部,快速实现凹形效果,核心是在Path中构建包含底部圆弧凹口的路径。
class BottomNotchClipper extends CustomClipper<Path> { final double notchRadius; BottomNotchClipper({this.notchRadius = 20.0}); @override Path getClip(Size size) { final path = Path() ..lineTo(0, size.height) // 左上角→左下角 ..lineTo(size.width / 2 - notchRadius, size.height) // 左半段底部直线 ..arcToPoint( Offset(size.width / 2 + notchRadius, size.height), radius: Radius.circular(notchRadius), clockwise: false, // 绘制向上的圆弧,形成凹口 ) ..lineTo(size.width, size.height) // 右半段底部直线 ..lineTo(size.width, 0) // 右下角→右上角 ..close(); // 闭合路径 return path; } @override bool shouldReclip(covariant CustomClipper<Path> oldClipper) { return oldClipper is BottomNotchClipper && oldClipper.notchRadius != notchRadius; } } // 使用示例 ClipPath( clipper: BottomNotchClipper(notchRadius: 30), child: Container( width: 300, height: 200, decoration: BoxDecoration( color: Colors.blue, boxShadow: [ BoxShadow(blurRadius: 10, color: Colors.black26, offset: Offset(0, 2)) ], ), ), )
方法二:使用CustomPaint直接绘制容器
如果需要更精细的控制(比如同步绘制阴影、边框),可以用CustomPaint直接画出带凹形的容器:
class NotchContainer extends StatelessWidget { final double width; final double height; final Color color; final double notchRadius; const NotchContainer({ super.key, required this.width, required this.height, this.color = Colors.blue, this.notchRadius = 20.0, }); @override Widget build(BuildContext context) { return CustomPaint( size: Size(width, height), painter: _NotchContainerPainter( color: color, notchRadius: notchRadius, ), ); } } class _NotchContainerPainter extends CustomPainter { final Color color; final double notchRadius; final Paint _paint; _NotchContainerPainter({ required this.color, required this.notchRadius, }) : _paint = Paint() ..color = color ..style = PaintingStyle.fill; @override void paint(Canvas canvas, Size size) { final path = Path() ..lineTo(0, size.height) ..lineTo(size.width / 2 - notchRadius, size.height) ..arcToPoint( Offset(size.width / 2 + notchRadius, size.height), radius: Radius.circular(notchRadius), clockwise: false, ) ..lineTo(size.width, size.height) ..lineTo(size.width, 0) ..close(); // 绘制阴影 canvas.drawShadow(path, Colors.black26, 8, true); // 绘制容器主体 canvas.drawPath(path, _paint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) { return oldDelegate is _NotchContainerPainter && (oldDelegate.color != color || oldDelegate.notchRadius != notchRadius); } } // 使用示例 NotchContainer( width: 300, height: 200, color: Colors.blue, notchRadius: 30, )
关键说明
arcToPoint的clockwise设为false会绘制向上的圆弧,形成凹口;设为true则是凸形。- 调整
notchRadius参数可以控制凹口的大小。 - 阴影效果:方法一通过Container的
decoration设置,方法二用canvas.drawShadow实现更贴合路径的自然阴影。
内容的提问来源于stack exchange,提问作者user11525495
相关产品推荐
相关产品推荐

