flutter圆形进度条-使用自定义圆形进度与画板实现

文章来源: https://mightytechno.com/flutter-circle-progress-using-custom-painter/

有多个使用案例,我们需要使用圈子进度,如显示健身进度,每周完成进度等。

您可以使用CustomPaint小部件在几分钟内在Flutter中实现循环进度,并为CustomPainter类提供自定义实现。

结构体

在进入编码之前,我们需要考虑结构。在这里,我们需要展示以下内容

  • 显示文本进度
  • 显示代表填充背景的完整圆圈
  • 显示显示当前进度的Arc
  • 显示进度时添加动画

履行

CustomPainter

在Scaffold体内,包裹我们的自定义小部件将允许在屏幕中央显示进度。

然后,您可以提供CustomPaint作为子窗口小部件。在这里,您需要显示文本小部件之外的进度。因此,您需要将CustomPainter小部件作为foregroundPainter传递

然后,您需要创建一个CustomProgress。要在动画发生时更改进度,我们需要将进度传递给窗口小部件。

正如我上面提到的,我们有两个圆圈来显示进度和实际进度的基础。为此,您需要创建一个两个绘制对象来绘制“完整圆”和“绘制圆弧”。检查此代码。


class CircleProgress extends CustomPainter{

  double currentProgress;

  CircleProgress(this.currentProgress);

  
  void paint(Canvas canvas, Size size) {

    //this is base circle
    Paint outerCircle = Paint()
        ..strokeWidth = 10
        ..color = Colors.black
        ..style = PaintingStyle.stroke;

    Paint completeArc = Paint()
      ..strokeWidth = 10
      ..color = Colors.redAccent
      ..style = PaintingStyle.stroke
      ..strokeCap  = StrokeCap.round;

    Offset center = Offset(size.width/2, size.height/2);
    double radius = min(size.width/2,size.height/2) - 10;

    canvas.drawCircle(center, radius, outerCircle); // this draws main outer circle

    double angle = 2 * pi * (currentProgress/100);

    canvas.drawArc(Rect.fromCircle(center: center,radius: radius), -pi/2, angle, false, completeArc);
  }

  
  bool shouldRepaint(CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return true;
  }
}

现在基本实现完成了。接下来我们可以添加一个动画来使这个更酷。

动画

In here you can use tween animation to start from 0 and end in the percentage which you want to show on the progress. Then you can assign the current animation value to the text and you can pass that as a parameter to CircleProgress class.


class _CircleProgressState extends State with SingleTickerProviderStateMixin {

  AnimationController progressController;
  Animation animation;

  
  void initState() {
    // TODO: implement initState
    super.initState();
    progressController = AnimationController(vsync: this,duration: Duration(milliseconds: 1000));
    animation = Tween(begin: 0,end: 80).animate(progressController)..addListener((){
      setState(() {

      });
    });
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: CustomPaint(

          foregroundPainter: CircleProgress(animation.value), // this will add custom painter after child
          child: Container(
            width: 200,
            height: 200,
            child: GestureDetector(
                onTap: (){
                  if(animation.value == 80){
                    progressController.reverse();
                  }else {
                    progressController.forward();
                  }
                },
                child: Center(child: Text("${animation.value.toInt()}%",style: TextStyle(
                  fontSize: 30,
                  fontWeight: FontWeight.bold
                ),))),
          ),
        ),

      ),
    );
  }
}

Check the Video

</div></figure></div>

0%