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

Flutter如何制作宽300高130、两侧半圆居中对齐的自定义形状Container

Flutter实现左右带垂直居中半圆缺口的自定义Container

实现该自定义容器推荐使用自定义ShapeBorder方案,可直接适配Container的阴影、边框等配置,无需额外剪裁处理,完整实现如下:

import 'package:flutter/material.dart';

// 自定义带缺口的卡片形状
class NotchedCardShape extends ShapeBorder {
  // 半圆缺口的半径,可按需调整
  final double notchRadius;
  // 卡片四个角的圆角大小,不需要圆角可设为0
  final double borderRadius;

  const NotchedCardShape({
    this.notchRadius = 15,
    this.borderRadius = 12,
  });

  @override
  EdgeInsetsGeometry get dimensions => EdgeInsets.zero;

  @override
  Path getInnerPath(Rect rect, {TextDirection? textDirection}) {
    return getOuterPath(rect, textDirection: textDirection);
  }

  @override
  Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
    final path = Path();
    // 容器高度方向中心点
    final centerY = rect.height / 2;

    // 绘制左上角+顶部边+右上角
    path.moveTo(rect.left + borderRadius, rect.top);
    path.lineTo(rect.right - borderRadius, rect.top);
    path.quadraticBezierTo(rect.right, rect.top, rect.right, rect.top + borderRadius);

    // 绘制右侧半圆缺口
    path.lineTo(rect.right, centerY - notchRadius);
    path.arcToPoint(
      Offset(rect.right, centerY + notchRadius),
      radius: Radius.circular(notchRadius),
      clockwise: false,
    );

    // 绘制右下角+底部边+左下角
    path.lineTo(rect.right, rect.bottom - borderRadius);
    path.quadraticBezierTo(rect.right, rect.bottom, rect.right - borderRadius, rect.bottom);
    path.lineTo(rect.left + borderRadius, rect.bottom);
    path.quadraticBezierTo(rect.left, rect.bottom, rect.left, rect.bottom - borderRadius);

    // 绘制左侧半圆缺口
    path.lineTo(rect.left, centerY + notchRadius);
    path.arcToPoint(
      Offset(rect.left, centerY - notchRadius),
      radius: Radius.circular(notchRadius),
      clockwise: false,
    );

    // 闭合路径
    path.lineTo(rect.left, rect.top + borderRadius);
    path.quadraticBezierTo(rect.left, rect.top, rect.left + borderRadius, rect.top);
    path.close();
    return path;
  }

  @override
  void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) {}

  @override
  ShapeBorder scale(double t) {
    return NotchedCardShape(
      notchRadius: notchRadius * t,
      borderRadius: borderRadius * t,
    );
  }
}

使用示例:

class DemoPage extends StatelessWidget {
  const DemoPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey.shade200,
      body: Center(
        child: Container(
          // 符合需求的固定尺寸
          width: 300,
          height: 130,
          decoration: ShapeDecoration(
            color: Colors.white,
            // 应用自定义形状
            shape: const NotchedCardShape(
              notchRadius: 15,
              borderRadius: 12,
            ),
            // 可直接配置阴影、边框等效果
            shadows: [
              BoxShadow(
                color: Colors.black.withOpacity(0.1),
                blurRadius: 8,
                offset: const Offset(0, 2),
              )
            ],
          ),
          // 内部自定义内容
          child: const Center(
            child: Text("自定义卡片内容", style: TextStyle(fontSize: 16)),
          ),
        ),
      ),
    );
  }
}
  • 调整notchRadius参数即可修改两侧半圆缺口的大小
  • 所有缺口位置基于容器尺寸自动计算,修改容器宽高后仍会保持左右垂直居中的效果

内容的提问来源于stack exchange,提问作者Jay Firke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 15:18:05