Flutter如何实现半圆温度进度条

在Flutter中如何实现一个半圆形的温度进度条?我想实现类似空调温度调节的效果,进度条从半圆的左侧开始向右填充,能够根据温度值动态变化。目前尝试了CustomPainter绘制,但不太清楚如何精确控制进度比例和动画效果。有没有比较成熟的实现方案或推荐的三方库?最好能支持自定义颜色、宽度和圆角等样式。

2 回复

使用CustomPaint绘制半圆,结合AnimationController控制温度进度。通过CustomPainterpaint方法,用drawArc绘制背景和进度弧线,设置strokeCap为圆角。动画驱动进度值变化,实现平滑过渡。

更多关于Flutter如何实现半圆温度进度条的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中实现半圆温度进度条,可以通过CustomPaint自定义绘制。以下是一个完整的实现示例:

import 'package:flutter/material.dart';

class SemiCircleProgressBar extends StatefulWidget {
  final double temperature;
  final double maxTemperature;
  
  const SemiCircleProgressBar({
    Key? key,
    required this.temperature,
    this.maxTemperature = 100,
  }) : super(key: key);

  @override
  _SemiCircleProgressBarState createState() => _SemiCircleProgressBarState();
}

class _SemiCircleProgressBarState extends State<SemiCircleProgressBar> 
    with SingleTickerProviderStateMixin {
  late AnimationController _controller;
  late Animation<double> _animation;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(milliseconds: 1500),
      vsync: this,
    );
    _animation = Tween<double>(
      begin: 0,
      end: widget.temperature / widget.maxTemperature,
    ).animate(_controller)
      ..addListener(() {
        setState(() {});
      });
    _controller.forward();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      size: const Size(200, 100),
      painter: _SemiCirclePainter(
        progress: _animation.value,
        temperature: widget.temperature,
      ),
    );
  }
}

class _SemiCirclePainter extends CustomPainter {
  final double progress;
  final double temperature;

  _SemiCirclePainter({
    required this.progress,
    required this.temperature,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final Paint backgroundPaint = Paint()
      ..color = Colors.grey[300]!
      ..style = PaintingStyle.stroke
      ..strokeWidth = 12
      ..strokeCap = StrokeCap.round;

    final Paint progressPaint = Paint()
      ..shader = LinearGradient(
        colors: [Colors.blue, Colors.red],
      ).createShader(Rect.fromCircle(
        center: Offset(size.width / 2, size.height),
        radius: size.width / 2,
      ))
      ..style = PaintingStyle.stroke
      ..strokeWidth = 12
      ..strokeCap = StrokeCap.round;

    // 绘制背景圆弧
    canvas.drawArc(
      Rect.fromCircle(
        center: Offset(size.width / 2, size.height),
        radius: size.width / 2,
      ),
      pi,
      pi,
      false,
      backgroundPaint,
    );

    // 绘制进度圆弧
    canvas.drawArc(
      Rect.fromCircle(
        center: Offset(size.width / 2, size.height),
        radius: size.width / 2,
      ),
      pi,
      pi * progress,
      false,
      progressPaint,
    );

    // 绘制温度文本
    final textStyle = TextStyle(
      color: Colors.black,
      fontSize: 24,
      fontWeight: FontWeight.bold,
    );
    final textSpan = TextSpan(
      text: '${temperature.toInt()}°C',
      style: textStyle,
    );
    final textPainter = TextPainter(
      text: textSpan,
      textAlign: TextAlign.center,
      textDirection: TextDirection.ltr,
    );
    textPainter.layout();
    textPainter.paint(
      canvas,
      Offset(
        (size.width - textPainter.width) / 2,
        size.height - textPainter.height - 10,
      ),
    );
  }

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

// 使用示例
SemiCircleProgressBar(
  temperature: 75,
  maxTemperature: 100,
)

关键实现点:

  1. 使用CustomPaintCustomPainter自定义绘制
  2. 通过drawArc方法绘制半圆弧形
  3. 添加动画效果使进度条平滑过渡
  4. 使用渐变颜色表示温度变化(蓝到红)
  5. 在中心位置显示当前温度数值

可自定义参数:

  • 温度值、最大温度值
  • 圆弧粗细、颜色
  • 动画时长
  • 文本样式

这个实现包含了完整的动画效果和温度显示,可以直接在项目中使用。

回到顶部