Flutter分段环周围数

vuktfyat  于 2023-02-13  发布在  Flutter
关注(0)|答案(1)|浏览(104)

在Flutter中,我试着在一个数字周围做一个分段环(或径向量规)来指示它的值。
链接中的例子本身已经是一个解决方案,但是,我读到syncfusion小部件不是免费的。(我正在商业上使用它)任何替代方案或想法如何将其付诸实践?

ecfsfe2w

ecfsfe2w1#

您可以使用CustomPainter来实现相同的目的,

class RingPainter extends CustomPainter {
  const RingPainter({
    required this.percentage,
    this.startColor,
    this.endColor,
    this.width,
  }) : assert(percentage >= 0 && percentage <= 100,
            "Percentage must be in the range 0-100!");

  final double percentage;
  final Color? startColor;
  final Color? endColor;
  final double? width;

  double get progress => percentage / 100;

  @override
  void paint(Canvas canvas, Size size) {
    var angle = math.pi / 180 * 230;
    canvas.rotateAroundCenter(size, angle);
    canvas.drawRing(
      size,
      1,
      startColor: Colors.black12,
      endColor: Colors.black12,
      width: width,
    );
    canvas.drawRing(
      size,
      progress,
      startColor: startColor,
      endColor: endColor,
      width: width,
    );
  }

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

extension on Canvas {
  rotateAroundCenter(Size size, double angleInRadians) {
    final double r =
        math.sqrt(size.width * size.width + size.height * size.height) / 2;
    final alpha = math.atan(size.height / size.width);
    final beta = alpha + angleInRadians;
    final shiftY = r * math.sin(beta);
    final shiftX = r * math.cos(beta);
    final translateX = size.width / 2 - shiftX;
    final translateY = size.height / 2 - shiftY;
    translate(translateX, translateY);
    rotate(angleInRadians);
  }

  drawRing(
    Size size,
    double value, {
    Color? startColor,
    Color? endColor,
    double? width,
  }) {
    final rect = Rect.fromLTWH(-15, 0.0, size.width, size.height);
    final gradient = SweepGradient(
      startAngle: 3 * math.pi / 2,
      endAngle: 7 * math.pi / 2,
      tileMode: TileMode.repeated,
      colors: [
        startColor ?? Colors.pink,
        endColor ?? Colors.blueAccent,
      ],
    );

    final paint = Paint()
      ..shader = gradient.createShader(rect)
      ..strokeCap = StrokeCap.round
      ..style = PaintingStyle.stroke
      ..strokeWidth = width ?? 24;

    final center = Offset(size.width / 2, size.height / 2);
    final radius =
        math.min(size.width / 2, size.height / 2) - ((width ?? 24) / 2);
    const startAngle = -math.pi / 2;
    final sweepAngle = 2 * math.pi * value * 0.723;

    drawArc(
      Rect.fromCircle(center: center, radius: radius),
      startAngle,
      sweepAngle,
      false,
      paint,
    );
  }
}

将其与CustomPaint小工具配合使用,

CustomPaint(
         painter: RingPainter(
         percentage: 70,
         width: 20,
       ),
   )

如果你想在戒指里写文字,

Center(
    child: SizedBox(
      width: 200,
      height: 200,
      child: Stack(
        fit: StackFit.expand,
        children: [
          const Center(
            child: Text(
              "70%",
              style: TextStyle(
                fontSize: 48,
                fontWeight: FontWeight.w900,
                color: Colors.purple,
              ),
            ),
          ),
          CustomPaint(
            painter: RingPainter(
              percentage: 70,
              width: 20,
            ),
          ),
        ],
      ),
    ),
  )

相关问题