Android自定义View——实现水波纹效果类似剩余流量球
三个点 pre ber block span 初始化 move 理解最近突然手痒就想搞个贝塞尔曲线做个水波纹效果玩玩,终于功夫不负有心人最后实现了想要的效果,一起来看下吧:
效果图镇楼
一:先一步一步来分解一下实现的过程
需要绘制一个正弦曲线(sin)或者余弦曲线(cos)
通过水平平移曲线来的到像水波波动的效果
水平移动的同时还需要有水位上涨,也就是向上平移
裁剪画布为圆形,在圆形区域绘制曲线
通过上面4步就可以实现了
二:现在就来实现第一步,绘制一个sin曲线;这里画了一张图来帮助理解,在PhotoShop中我们绘制一个贝塞尔曲线可以清楚的看到它的控制点如图:
绘制贝塞尔曲线我们必须要知道三个点:起点、控制点、终点;有了这三个点我们就可以绘制一段简单二阶贝塞尔曲线。从图中我们可以看出 起点 控制点p1 x1 这三个点绘制了一段曲线,也就是通过path.quadTo()函数添加一个曲线路径。
???假设我们需要绘制一个周期的sin曲线,那么我们就只需要知道起点、一个周期的宽度、振幅;就可以绘制一个sin曲线了。
三:下面就来看下代码的实际操作了,这里就直接省略掉一些画笔初始化的操作了可以点击这里查看源码
protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec){
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
//获取view的宽度
width=getViewSize(800,widthMeasureSpec);
//获取view的高度
height=getViewSize(400,heightMeasureSpec);
//获取起点坐标
startPoint=newPoint(0,height/2);
}
1
2
3
4
5
6
7
8
9
首先肯定是要获取到画布的大小才能确定好起点的坐标,有了起点坐标就可以开始绘制我们的曲线了
在ondraw()函数中进行曲线的绘制
/*sin曲线 1/4个周期的宽度*/
privateintcycle=200;
/*sin曲线振幅的高度*/
privateintwaveHeight=200;
@Override
protectedvoidonDraw(Canvascanvas){
super.onDraw(canvas);
path.moveTo(startPoint.x,startPoint.y);
intj=1;
//循环绘制正弦曲线 循环一次半个周期
for(inti=1;i<=8;i++){
if(i%2==0){
//波峰
path.quadTo(startPoint.x+(cycle*j),startPoint.y+waveHeight,
startPoint.x+(cycle*2)*i,startPoint.y);
}else{
//波谷
path.quadTo(startPoint.x+(cycle*j),startPoint.y-waveHeight,
startPoint.x+(cycle*2)*i,startPoint.y);
}
j+=2;
}
//绘制封闭的曲线
path.lineTo(width,height);//右下角
path.lineTo(startPoint.x,height);//左下角
path.lineTo(startPoint.x,startPoint.y);//起点
path.close();
canvas.drawPath(path,paint);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
经过上面一系例操作一个水波纹效果就出来啦
四:接下来就是水平移动这个曲线了为了移动起来更加好看,我们需要在屏幕外面开始绘制一个周期,如下:
//初始化的时候将起点移至屏幕外一个周期
startPoint=newPoint(-cycle*4,height/2);
//继续在ondraw()函数最后追加平移代码
//判断是不是平移完了一个周期
if(startPoint.x+40>=0){
//满了一个周期则恢复默认起点继续平移
startPoint.x=-cycle*4;
}
//每次波形的平移量 40
startPoint.x+=40;
postInvalidateDelayed(150);
path.reset();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
只需要这样就可以产生水波效果了,一起来看效果图吧。
五:接下来就是要将画布变成圆形了(其实还是个矩形,只是绘画区域在你所裁剪的区域),然后在里面实现水波纹就哦的K了;完整的绘制代码如下:
@OverrideprotectedvoidonDraw(Canvascanvas){
super.onDraw(canvas);
//裁剪画布为圆形
PathcirclePath=newPath();
circlePath.addCircle(width/2,height/2,width/2,Path.Direction.CW);
canvas.clipPath(circlePath);
canvas.drawPaint(circlePaint);
canvas.drawCircle(width/2,height/2,width/2,circlePaint);
//以下操作都是在这个圆形画布中操作
//根据进度改变起点坐标的y值
startPoint.y=(int)(height-(progress/100.0*height));
//起点
path.moveTo(startPoint.x,startPoint.y);
intj=1;
//循环绘制正弦曲线 循环一次半个周期
for(inti=1;i<=8;i++){
if(i%2==0){
path.quadTo(startPoint.x+(cycle*j),startPoint.y+waveHeight,startPoint.x+(cycle*2)*i,startPoint.y);
}else{
path.quadTo(startPoint.x+(cycle*j),startPoint.y-waveHeight,startPoint.x+(cycle*2)*i,startPoint.y);
}
j+=2;
}
//绘制封闭的曲线
path.lineTo(width,height);//右下角
path.lineTo(startPoint.x,height);//左下角
path.lineTo(startPoint.x,startPoint.y);//起点
path.close();
canvas.drawPath(path,paint);
drawText(canvas,textPaint,progress+"%");
//判断是不是平移完了一个周期
if(startPoint.x+40>=0){
//满了一个周期则恢复默认起点继续平移
startPoint.x=-cycle*4;
}
//每次波形的平移量 40
startPoint.x+=40;
if(autoIncrement){
if(progress>=100){
progress=0;
}else{
progress++;
}
}
postInvalidateDelayed(150);
path.reset();
}
Android自定义View——实现水波纹效果类似剩余流量球
来源: http://www.bubuko.com/infodetail-2294788.html