Flutter实现左侧动态填充星级评分组件 如何避免堆叠粗糙写法
无需Stack堆叠的星级评分组件实现方案
核心思路
完全在单个CustomPainter内完成所有绘制逻辑,不需要嵌套多层组件:
- 复用五角星Path,先绘制描边作为边框,替代原来的双层组件堆叠方案,边框宽度可自定义
- 通过
canvas.clipPath()将绘制区域限定为五角星形状,直接绘制对应宽度的填充矩形实现左侧填充效果,无需ShaderMask渐变模拟 - 动态参数变更时触发重绘即可实现进度更新
完整改造代码
改造后的StarPainter
import 'package:flutter/material.dart'; class StarPainter extends CustomPainter { // 填充百分比 取值范围0~1 final double percent; // 边框宽度 final double strokeWidth; // 边框颜色 final Color strokeColor; // 填充颜色 final Color fillColor; StarPainter({ required this.percent, this.strokeWidth = 2, this.strokeColor = Colors.black, this.fillColor = Colors.black, }); @override void paint(Canvas canvas, Size size) { double w = size.width; double h = size.height; // 复用五角星Path Path starPath = Path() ..moveTo(0, (2 * h) / 5) ..lineTo(w, (2 * h) / 5) ..lineTo(w / 5, h) ..lineTo(w / 2, 0) ..lineTo((4 * w) / 5, h) ..lineTo(0, (2 * h) / 5) ..close(); // 1. 绘制五角星边框 Paint strokePaint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = strokeWidth ..color = strokeColor; canvas.drawPath(starPath, strokePaint); // 2. 裁剪绘制区域为五角星形状 canvas.clipPath(starPath); // 3. 绘制对应宽度的填充矩形,实现左侧填充效果 Paint fillPaint = Paint() ..style = PaintingStyle.fill ..color = fillColor; canvas.drawRect( Rect.fromLTWH(0, 0, w * percent, h), fillPaint, ); } @override bool shouldRepaint(covariant StarPainter oldDelegate) { // 参数变化时触发重绘 return oldDelegate.percent != percent || oldDelegate.strokeWidth != strokeWidth || oldDelegate.strokeColor != strokeColor || oldDelegate.fillColor != fillColor; } }
使用示例
class StarRatingDemo extends StatelessWidget { // 五角星尺寸 final double starSize = 100; // 填充进度 final double fillPercent = 0.8; const StarRatingDemo({super.key}); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: Center( child: SizedBox( height: starSize, width: starSize, // 直接使用CustomPaint,无需Stack嵌套 child: CustomPaint( painter: StarPainter( percent: fillPercent, strokeWidth: 2, strokeColor: Colors.black, fillColor: Colors.amber, ), ), ), ), ), ); } }
额外优化说明
如果要实现多星评分,直接循环生成多个对应尺寸的CustomPaint组件即可,每个星星可单独配置填充进度,整体结构更简洁,渲染性能也优于多层Stack堆叠方案。
内容的提问来源于stack exchange,提问作者user5381191
相关产品推荐
相关产品推荐

