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
相关产品推荐
相关产品推荐

