You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 03:01:07