Flutter实例代码:波浪圆形进度条

2019-06-1509:25:53APP与小程序开发Comments3,730 views字数 3453阅读模式

效果图文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/13602.html

Flutter实例代码:波浪圆形进度条

实现步骤

绘制进度条

Flutter实例代码:波浪圆形进度条
  1. 先绘制绘制波浪
     void drawWave(Canvas canvas, Offset center, double radius,
         double waveOffsetPercent, Paint paint) {
       double waveOffset = -(waveOffsetPercent * radius * 2);
       //对画布进行圆形裁剪
       canvas.save();
       Path clipPath = Path()
         ..addOval(Rect.fromCircle(center: center, radius: radius));
       canvas.clipPath(clipPath);
     
       //表示出上图所示的point(上图中p)以及controlPoint(上图中c)
       double waveProgressHeightY = (1 - percent) * radius * 2;
       Offset point1 = Offset(waveOffset, waveProgressHeightY);
       Offset point2 = Offset(waveOffset + radius, waveProgressHeightY);
       Offset point3 = Offset(waveOffset + radius * 2, waveProgressHeightY);
       Offset point4 = Offset(waveOffset + radius * 3, waveProgressHeightY);
       Offset point5 = Offset(waveOffset + radius * 4, waveProgressHeightY);
       Offset point6 = Offset(point5.dx, radius * 2 + halfWaveHeight);
       Offset point7 = Offset(point1.dx, radius * 2 + halfWaveHeight);
       Offset controlPoint1 =
           Offset(waveOffset + radius * 0.5, waveProgressHeightY - halfWaveHeight);
       Offset controlPoint2 =
           Offset(waveOffset + radius * 1.5, waveProgressHeightY + halfWaveHeight);
       Offset controlPoint3 =
           Offset(waveOffset + radius * 2.5, waveProgressHeightY - halfWaveHeight);
       Offset controlPoint4 =
           Offset(waveOffset + radius * 3.5, waveProgressHeightY + halfWaveHeight);
       //完成path的链接
       Path wavePath = Path()
         ..moveTo(point1.dx, point1.dy)
         ..quadraticBezierTo(
             controlPoint1.dx, controlPoint1.dy, point2.dx, point2.dy)
         ..quadraticBezierTo(
             controlPoint2.dx, controlPoint2.dy, point3.dx, point3.dy)
         ..quadraticBezierTo(
             controlPoint3.dx, controlPoint3.dy, point4.dx, point4.dy)
         ..quadraticBezierTo(
             controlPoint4.dx, controlPoint4.dy, point5.dx, point5.dy)
         ..lineTo(point6.dx, point6.dy)
         ..lineTo(point7.dx, point7.dy)
         ..close();
       //完成绘制
       canvas.drawPath(wavePath, paint);
       canvas.restore();
     }
    复制代码
  2. 绘制层叠的波浪,跟第一步一样的绘制方法,可以将颜色与偏移值跟第一个波浪错开
  3. 绘制圆形进度内容,这一步需要注意的是在绘制进度的时候,需要对画布进行旋转,具体绘制内容如下
     void drawCircleProgress(
         Canvas canvas,
         Offset center,
         double radius,
         Size size) {
       //画进度条圆框背景
       canvas.drawCircle(center, radius, circleProgressBGPaint);
       //保存画布状态
       canvas.save();
       //逆时针旋转画布90度
       canvas.rotate(degreeToRadian(-90));
       canvas.translate(
           -(size.height + size.width) / 2, -(size.height - size.width) / 2);
       //画进度条圆框进度
       canvas.drawArc(
           Rect.fromCircle(center: center, radius: radius),
           degreeToRadian(0),
           degreeToRadian(percent * 360),
           false,
           circleProgressPaint);
       //恢复画布状态
       canvas.restore();
     }
    复制代码

绘制工作基本就差不多完成了文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/13602.html

让波浪动起来

利用动画更改波浪的偏移值,并使动画不停的进行重复。两个波浪偏移的速度设置成不一致的,让波浪看起来更协调文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/13602.html

  void initState() {
    super.initState();
    waveAnimation = AnimationController(
      vsync: this,
      duration: widget.waveAnimationDuration,
    );
    waveAnimation.addListener(waveAnimationListener);
    lightWaveAnimation = AnimationController(
      vsync: this,
      duration: widget.lightWaveAnimationDuration,
    );
	//在lightWaveAnimationListener中获取波浪最新的偏移值,刷新状态
    lightWaveAnimation.addListener(lightWaveAnimationListener);
    waveAnimation.repeat();
    lightWaveAnimation.repeat();
  }
复制代码

完成波浪动起来的效果之后基本上就差不多了,但是会有一个很明显的问题,那就是在设置进度之后,进度条中的波浪是瞬间涨上去,看上去非常的不协调,所以我们还需要给进度条加上一个,进度更改时的动画效果。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/13602.html

让波浪缓缓升起来降下去

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
        vsync: this, duration: widget.progressAnimatedDuration);
    controller.addStatusListener((status) {
	  //当动画结束时重置动画
      if (status == AnimationStatus.completed) {
        progressAnimation.removeListener(handleProgressChange);
        controller.reset();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
	//当进度发生改变时,开始动画
    if (currentValue != widget.value && !controller.isAnimating) {
      progressAnimation =
          controller.drive(IntTween(begin: currentValue, end: widget.value));
      progressAnimation.addListener(handleProgressChange);
      controller.forward();
    }
    ...
  }
复制代码

在进度改变时,我们通过一个动画来改变进度到指定的进度,这样就保证了,进度发生改变时,波浪不会瞬间涨上去。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/13602.html

作者:kevinxie
链接:https://juejin.im/post/5d008a4c518825668a3745ed
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/13602.html

文章源自菜鸟学院-https://www.cainiaoxueyuan.com/xcx/13602.html
  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/xcx/13602.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定