如何在Flutter中绘制如图所示的左上角带价格绿色自定义形状?
实现左上角带价格的绿色角标方案
方案一:旋转容器快速实现
适合快速开发,通过旋转Container实现斜角效果,代码简单易调整:
自定义角标Widget
class PriceTag extends StatelessWidget { final String price; final Color bgColor; final TextStyle textStyle; const PriceTag({ super.key, required this.price, this.bgColor = Colors.green, this.textStyle = const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.bold), }); @override Widget build(BuildContext context) { return Transform( transform: Matrix4.rotationZ(-0.2), // 调整旋转角度控制倾斜程度 origin: const Offset(0, 0), child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), decoration: BoxDecoration( color: bgColor, borderRadius: const BorderRadius.only(bottomRight: Radius.circular(8)), ), child: Text(price, style: textStyle), ), ); } }
整合到现有Item Widget
用Stack将角标叠加在原有Item的左上角:
class CustomItemWidget extends StatelessWidget { final String title; final String price; const CustomItemWidget({super.key, required this.title, required this.price}); @override Widget build(BuildContext context) { return Stack( children: [ // 你的原有Item内容(替换成你已实现的Widget) Container( width: 150, height: 200, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: const [BoxShadow(color: Colors.black12, blurRadius: 4)], ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.shopping_bag, size: 40), const SizedBox(height: 12), Text(title), ], ), ), // 左上角价格角标 const Positioned( top: 0, left: 0, child: PriceTag(price: "\$19.99"), ), ], ); } }
方案二:自定义ClipPath实现精准斜角
如果需要更贴合设计的斜切形状,用ClipPath自定义路径:
自定义裁剪路径
class DiagonalClipPath extends CustomClipper<Path> { @override Path getClip(Size size) { final path = Path(); path.lineTo(size.width, 0); path.lineTo(size.width - 25, size.height); // 调整数值控制斜角长度 path.lineTo(0, size.height); path.close(); return path; } @override bool shouldReclip(covariant CustomClipper<Path> oldClipper) => false; }
更新PriceTag Widget
@override Widget build(BuildContext context) { return ClipPath( clipper: DiagonalClipPath(), child: Container( width: 65, height: 32, color: bgColor, alignment: Alignment.centerLeft, padding: const EdgeInsets.only(left: 8), child: Text(price, style: textStyle), ), ); }
注意事项
- 调整旋转角度、裁剪路径数值、容器尺寸可以匹配你的设计需求
- 如果原有Item有内边距,需要同步调整
Positioned的top/left参数确保角标位置正确 - 可根据需求修改背景色、文本样式、圆角等属性
内容的提问来源于stack exchange,提问作者Kalpesh Khandla
相关产品推荐
相关产品推荐

