在Flutter中使用Canvas绘制弧形进度条


啊…这…

这种很鸡肋的需求,是来自WX某公众号推送的恰饭文章中偶然发现的,整体为弧形卡片设计的音乐播放器,包括音乐播放的进度条,而后觉得弧形进度条因吹斯汀,翻遍已有的Flutter教程帖后,并没有发现类似的帖子,所以我来了!

value值为0时
value值改变时

本人Flutter萌新,第一次发文章,代码写的比较烂,还望大佬嘴下留情…

话不多说,直接开整:

一、进度条的属性以及成员变量

Flutter中为我们提供了封装好的组件CustomerPaint Widget,这个组件与画笔Paint Widget组合使用就可以绘制出需要的图形,在这之前,我们需要先创建一个继承于基类的绘制类。

进度条最直观的就是颜色,因此就需要前景色和背景色,初次之外还有其他参数,这里就不一一列举了,直接上代码:

由于CSDN的Markdown并不支持Dart,因此使用了js的高亮支持

class Progress extends CustomPainter {
  final Color backgroundColor;		//背景色
  final Color progressColor;		//前景色
  final double startPointAngle;		//Canvas绘制开始位置
  final double endPointAngle;		//结束位置
  final bool centerClose;			//圆弧是否闭合
  final double radius;				//半径
  final double lineWidth;			//所绘制线条的宽度
  final double value;				//进度条的value
  final TextStyle style;			//进度条文本风格(非必须)
  final String completeText;		//进度条文本(非必须)

  const Progress(
      {this.backgroundColor,
      this.progressColor,
      this.startPointAngle,
      this.endPointAngle,
      this.centerClose,
      this.radius,
      this.lineWidth,
      this.value,
      this.style,
      this.completeText});
}

如上所述,列举了一些基本的属性,也可以根据需要添加其他参数

二、初始化画笔Paint,调用Canvas绘制图形

在绘制类中重写paint()shouldRepaint()方法

在我们所创建的继承于基类CustomPainter的绘制类中,会有如下两个方法,需要我们进行重写:

class ProgresPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    // TODO: implement paint
  }
  
  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return null;
  }

重写paint()方法:

void paint(Canvas canvas, Size size) {
    // TODO: implement paint
    Paint paint = Paint()	//初始化画笔
      ..color = backgroundColor	//背景颜色
      ..style = PaintingStyle.stroke	//画笔样式
      ..strokeCap = StrokeCap.round	//画笔笔头类型
      ..strokeWidth = lineWidth;	//画笔的宽度
    Rect rect = Rect.fromCircle(
        center: Offset(size.width / 2, size.height / 2), radius: radius);
        
//通过Canvas绘制一条弧线
    canvas.drawArc(rect, startPointAngle, endPointAngle, centerClose, paint);
//背景弧线绘制完成

    paint
      ..color = progressColor	//前景色
      ..strokeWidth = lineWidth + 1.0	//画笔宽度,在这里我们设置得比背景的宽度稍宽些
      ..style = PaintingStyle.stroke
      ..strokeCap = StrokeCap.round;
    canvas.drawArc(
        rect, startPointAngle, endPointAngle * value, centerClose, paint);
  }
//前景弧线绘制完成

重写shouldRepaint()方法:

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

三、在其他Widget中使用绘制好的进度条

为了更快捷的预览到进度条的效果,在这里我们直接使用SliderWidget来控制value的值。
首先,创建一个StatefulWidget

class ArcProgress extends StatefulWidget {
  double value;	//在其他地方调用该Widget时,可以直接给value赋值

  ArcProgress({
    this.value,
  });
  @override
  _ArcProgressState createState() => _ArcProgressState();
}

class _ArcProgressState extends State<ArcProgress> {
  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      child: Slider(	//在这里我们直接使用Slider对value进行赋值,实际使用时,应当移除
          value: widget.value,
          onChanged: (value) {
            setState(() {
              widget.value = value;
            });
          }),
      painter: Progress(
          backgroundColor: Colors.grey,	//设置背景色
          progressColor: Colors.amber,	//设置前景色
          radius: MediaQuery.of(context).size.width,	//设置背景色
          lineWidth: 5.0,	//设置线条宽度(此处为背景线条宽度)
          startPointAngle: math.pi - (math.pi / 9),	//设置起始点
          endPointAngle: -(7 * math.pi / 9),
          centerClose: false,	//是否闭合,闭合后即为扇形
          value: widget.value,
      ),
    );
  }
}

在其他Widget中直接使用CustomPainter绘制的图形时,一定要在父控件的child里使用CustomPaint进行包裹

到这里,就已经完成了绘制和使用了。此文章并没有什么技术可言,初次发文,希望大家见谅

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值