Flutter - 自定义进度条

Flutter - custom progress bar

提问人:Vito 提问时间:5/24/2023 最后编辑:Vito 更新时间:5/24/2023 访问量:67

问:

我真的被这种弯曲的进度条困住了,带有溢出进度的自定义颜色(这些三角形)。有什么想法如何实现它吗?

enter image description here

这就是我目前所拥有的 - 只是一个带有价值的弯曲进度条,但我不知道如何使用这些渐变三角形前进:

 class ConvexProgressPainter extends CustomPainter {
  int progress;
  ConvexProgressPainter({required this.progress});

  @override
  void paint(Canvas canvas, Size size) {
    final quadraticCurve = QuadraticBezier([
      vmath.Vector2(0, size.height),
      vmath.Vector2(size.width / 2, 0),
      vmath.Vector2(size.width, size.height),
    ]);

    // Render main background points
    final fullControlPoints = List.generate(size.width.toInt(), (index) {
      final point = quadraticCurve.pointAt(index.toDouble() / size.width);
      return Offset(
        point.x,
        point.y,
      );
    }).toList();

    final mainSpline = CatmullRomSpline(fullControlPoints);
    final mainBezierPaint = Paint()
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 20
      ..shader = LinearGradient(colors: [
        HexColor.fromHex('FFC738'),
        HexColor.fromHex('FF1886'),
      ]).createShader(Offset(0, size.height) & size);

    canvas.drawPoints(
      PointMode.points,
      mainSpline.generateSamples().map((e) => e.value).toList(),
      mainBezierPaint,
    );

    // Render progress points
    final progressValue = progress * (size.width / 120);

    final progressControlPoints = List.generate(progressValue.toInt(), (index) {
      final point = quadraticCurve.pointAt(index.toDouble() / size.width);
      return Offset(
        point.x,
        point.y,
      );
    }).toList();

    var progressTextAngle = 3;
    final progressSpline = CatmullRomSpline(progressControlPoints);
    final progressBezierPaint = Paint()
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 20
      ..shader = LinearGradient(colors: [
        HexColor.fromHex('0063FF'),
        HexColor.fromHex('6000FF'),
      ]).createShader(Offset(0, size.height) & size);

    canvas.drawPoints(
      PointMode.points,
      progressSpline.generateSamples().map((e) => e.value).toList(),
      progressBezierPaint,
    );

    // rotate the canvas
    canvas.save();

    final radians = progressTextAngle * pi / 180;
    canvas.rotate(radians);

    TextSpan span = TextSpan(
        style: AppTheme.caption.copyWith(color: Colors.white, fontSize: 10),
        text: '$progress%');
    TextPainter tp = TextPainter(text: span, textDirection: TextDirection.ltr);
    tp.layout();
    final x = progressControlPoints.last.dx;
    final y = progressControlPoints.last.dy - tp.size.height / 2 - 2;
    rotate(canvas, x, y, radians, tp);
    //tp.paint(canvas, Offset(x, y));

    canvas.restore();
  }

  void rotate(
      Canvas canvas, double cx, double cy, double angle, TextPainter tp) {
    // Calculate delta offset with reference to which any text should
    // paint, such that the centre of the text will be
    // at the given textCentrePoint
    final delta = Offset(cx - tp.size.width, cy - tp.size.height);

    canvas.save();
    canvas.translate(cx, cy);
    canvas.rotate(angle);
    canvas.translate(-cx, -cy);
    tp.paint(canvas, delta);
    canvas.restore();
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}

目前看起来是这样的:enter image description here

颤振 进度

评论


答:

0赞 Tim 5/24/2023 #1

我会将您的画布保留为堆栈的顶部元素,同时让红色/粉红色部分是透明的。堆栈的下层可以是略微旋转的容器,其中包含渐变。轻微的旋转是这样完成的。

new RotationTransition(
  turns: new AlwaysStoppedAnimation(45 / 360),
  child: Container(),
)