自定义一个水波进度球
最终样式:
1.自定义View
在Flutter中自定义View需要继承CustomPainter
控件,需要实现两个方法:
void paint(Canvas canvas, Size size)
以及bool shouldRepaint(CustomPainter oldDelegate)
,重要的方法当然就是前者,如何在画布上画出我们想要的图案;
至于CusetomPainter控件的使用如下:
Container(
width: 200.0,
height: 200.0,
child: new WavePainter(),
),
2.绘制波浪
绘制波浪的原理其实很简单,重点就是使用path
贝塞尔曲线的使用,绘制如下:
Path path = new Path()
..moveTo(waveCenter.dx - width, waveCenter.dy)
..lineTo(waveCenter.dx - width, center.dy + height / 2)
..lineTo(waveCenter.dx + width, center.dy + height / 2)
..lineTo(waveCenter.dx + width, waveCenter.dy);
..quadraticBezierTo(
waveCenter.dx +
width*3/4,
waveCenter.dy + waveHeight,
waveCenter.dx +
width * 1/2,
waveCenter.dy)
..quadraticBezierTo(
waveCenter.dx +
width*1/4,
waveCenter.dy - waveHeight,
waveCenter.dx,
waveCenter.dy)
..quadraticBezierTo(
waveCenter.dx -
width*1/4,
waveCenter.dy + waveHeight,
waveCenter.dx -
width * 1/2,
waveCenter.dy)
..quadraticBezierTo(
waveCenter.dx -
width*3/4,
waveCenter.dy - waveHeight,
waveCenter.dx -
width,
waveCenter.dy);
然后使用canvas
进行绘制:
canvas.drawPath(path, paint);
这里其实绘制了两段重复的波浪,然后在后面使用一个动画让它向右平移width
的宽度,然后重复动画,这样在给定的视野框中就像是波浪一直向右滚动。
这里我们需要在波浪外套上一层圆形,然后让圆形内的波浪显示,而圆形外的波浪隐藏,就使用到了paint
的blendMode
属性,这个属性的值有很多种,兄弟们自行了解,这里使用到的如下:
paint..blendMode = BlendMode.srcATop
具体代码如下:
var paint = new Paint()
..color = circleBackgroundColor
..style = PaintingStyle.fill;
canvas.drawCircle(center, min(width, height) / 2, paint);
paint
..blendMode = BlendMode.srcATop
..style = PaintingStyle.fill
..strokeWidth = 2.0;
canvas.drawPath(paint, paint);
然后我们可以在中加入一个显示进度的文字,使用TextPainter
进行绘制:
TextPainter tp = TextPainter(
text: TextSpan(
text: '${(yAnimValue * 100.0).toStringAsFixed(0)}%',
style: textStyle),
textDirection: TextDirection.rtl)
..layout();
tp.paint(
canvas, Offset(center.dx - tp.width / 2, center.dy - tp.height / 2));
3.加入进度功能
加入进度的功能也就是为了能让波浪能够由下至上填满,和波浪平移一样,这里给一个动画:
yController = new AnimationController(
vsync: this, duration: Duration(milliseconds: 500));
yAnimation = new Tween(begin: 0.0, end: 1.0).animate(yController);
yAnimation.addListener(_onProgressChange);
yAnimation.addStatusListener(_onProgressStatusChange);
void _onProgressChange() {
setState(() {
curProgress = yAnimation.value;
});
}
void _onProgressStatusChange(status) {
if (status == AnimationStatus.completed) {
onProgressChange();
}
}
让后让波浪的高度由这个动画数值来控制,这里刷新的远离就是当动画数值变化的时候,调用StatefulWidget
的setState({})
进行界面刷新。
4.波浪特效
对于滚动的波浪我们可以加入以下特效:
paint..maskFilter = MaskFilter.blur(BlurStyle.inner, 10.0)
通过maskFilter
属性我们可以设置绘制区域高斯模糊,这里设置强度为10.0,方向为向内
对于显示的文字我们也加入特效:
TextStyle(
fontSize: 60.0,
foreground: Paint()
..color = Colors.lightBlue
..style = PaintingStyle.fill
..strokeWidth = 2.0
..blendMode = BlendMode.difference
..colorFilter = ColorFilter.mode(Colors.white, BlendMode.exclusion)
..maskFilter = MaskFilter.blur(BlurStyle.solid, 1.0),
fontWeight: FontWeight.bold,
),
blendMode
表示绘制有重叠的区域颜色区别处理,然后colorFilter
表示对绘制的颜色与白色进行混色,就可以做出,波浪经过的时候文字水中与不在水中的部分有不同的颜色。