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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 21:24:04