繁体   English   中英

Flutter 圆形进度指示器-可重复-定制画家

[英]Flutter circular progress indicator - repeatable-Custom painter

我想创造这样的东西:想要实现

我已经做到了:到现在为止

我正在努力在这个圆形进度条的 state 处添加垂直线,就像尾随处的线一样。

import 'dart:math';

import 'package:flutter/material.dart';

class LoaderPaint extends CustomPainter {
  final double percentage;
  LoaderPaint({
    required this.percentage,
  });

  deg2Rand(double deg) => deg * pi / 180;

  @override
  void paint(Canvas canvas, Size size) {
    final midOffset = Offset(size.width / 2, size.height / 2);

    final paint = Paint()
      ..strokeCap = StrokeCap.round
      ..color = Colors.white
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2;

    canvas.drawLine(
      Offset(midOffset.dy, 10),
      Offset(midOffset.dy,-10),
      paint,
    );
    canvas.drawArc(
      Rect.fromCenter(center: midOffset, width: size.width, height: size.height),
      deg2Rand(-90),
      deg2Rand(360 * percentage),
      false,
      paint,
    );

  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}
  1. 使用此stackoverflow 答案中的公式计算行的末尾 position。 由于我们从 -90 度开始角度,因此我们必须将其从 sweepAngle 中移开。

  2. 使用此答案中的公式计算直线末端 position 前后 10 个单位的点,插入圆心和直线末端 position。

  3. canvas.drawLine画线

以下是更新后的LoaderPaint class 与这些更改后的样子:

class LoaderPaint extends CustomPainter {
  final double percentage;
  const LoaderPaint({
    required this.percentage,
  });

  deg2Rand(double deg) => deg * pi / 180;

  @override
  void paint(Canvas canvas, Size size) {
    final radius = size.width / 2;
    final sweepAngle = deg2Rand(360 * percentage);
    final theta = deg2Rand(-90) + sweepAngle;
    
    final midOffset = Offset(radius, radius);
    final endOffset = Offset(radius + radius * cos(theta), radius + radius * sin(theta));
    
    final midEndDiff = sqrt(pow(endOffset.dx - midOffset.dx, 2) + pow(endOffset.dy - midOffset.dy, 2));

    final paint = Paint()
      ..strokeCap = StrokeCap.round
      ..color = Colors.white
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2;

    canvas.drawLine(
      Offset(midOffset.dy, 10),
      Offset(midOffset.dy,-10),
      paint,
    );
    canvas.drawArc(
      Rect.fromCenter(center: midOffset, width: size.width, height: size.height),
      deg2Rand(-90),
      sweepAngle,
      false,
      paint,
    );
    canvas.drawLine(
      Offset(endOffset.dx + (10/midEndDiff) * (endOffset.dx - midOffset.dx), endOffset.dy + (10/midEndDiff) * (endOffset.dy - midOffset.dy)),
      Offset(endOffset.dx - (10/midEndDiff) * (endOffset.dx - midOffset.dx), endOffset.dy - (10/midEndDiff) * (endOffset.dy - midOffset.dy)),
      paint,
    );

  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true;
  }
}

这个 dartpad显示它工作正常。 您可以轻松更改百分比以查看它在各个角度的工作情况。

您必须记住,这仅在CustomPaint小部件的宽度和高度完全相同的情况下才有效,但是如果宽度和高度不同,您的没有端盖的示例也会中断。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM