Android自定义View——实现水波纹效果类似剩余流量球

归志宁无五亩园,读书本意在元元。这篇文章主要讲述Android自定义View——实现水波纹效果类似剩余流量球相关的知识,希望能为你提供帮助。

最近突然手痒就想搞个贝塞尔曲线做个水波纹效果玩玩,终于功夫不负有心人最后实现了想要的效果,一起来看下吧:
效果图镇楼
Android自定义View——实现水波纹效果类似剩余流量球

文章图片

一:先一步一步来分解一下实现的过程
  1. 需要绘制一个正弦曲线(sin)或者余弦曲线(cos)
  2. 通过水平平移曲线来的到像水波波动的效果
  3. 水平移动的同时还需要有水位上涨,也就是向上平移
  4. 裁剪画布为圆形,在圆形区域绘制曲线
  5. 通过上面4步就可以实现了
二:现在就来实现第一步,绘制一个sin曲线;这里画了一张图来帮助理解,在PhotoShop中我们绘制一个贝塞尔曲线可以清楚的看到它的控制点如图:
Android自定义View——实现水波纹效果类似剩余流量球

文章图片
         
Android自定义View——实现水波纹效果类似剩余流量球

文章图片

???绘制贝塞尔曲线我们必须要知道三个点:起点、控制点、终点;有了这三个点我们就可以绘制一段简单二阶贝塞尔曲线。从图中我们可以看出 起点 控制点p1 x1 这三个点绘制了一段曲线,也就是通过path.quadTo()函数添加一个曲线路径。 
???假设我们需要绘制一个周期的sin曲线,那么我们就只需要知道起点、一个周期的宽度、振幅;就可以绘制一个sin曲线了。
三:下面就来看下代码的实际操作了,这里就直接省略掉一些画笔初始化的操作了可以点击这里查看源码
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //获取view的宽度 width = getViewSize(800, widthMeasureSpec); //获取view的高度 height = getViewSize(400, heightMeasureSpec); //获取起点坐标 startPoint = new Point(0, height / 2); }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
首先肯定是要获取到画布的大小才能确定好起点的坐标,有了起点坐标就可以开始绘制我们的曲线了
在ondraw()函数中进行曲线的绘制
/*sin曲线 1/4个周期的宽度*/ private int cycle = 200; /*sin曲线振幅的高度*/ private int waveHeight = 200; @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); path.moveTo(startPoint.x, startPoint.y); int j = 1; //循环绘制正弦曲线 循环一次半个周期 for (int i = 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
经过上面一系例操作一个水波纹效果就出来啦
Android自定义View——实现水波纹效果类似剩余流量球

文章图片

四:接下来就是水平移动这个曲线了为了移动起来更加好看,我们需要在屏幕外面开始绘制一个周期,如下:
//初始化的时候将起点移至屏幕外一个周期 startPoint = new Point(-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
只需要这样就可以产生水波效果了,一起来看效果图吧。【Android自定义View——实现水波纹效果类似剩余流量球】
Android自定义View——实现水波纹效果类似剩余流量球

文章图片

五:接下来就是要将画布变成圆形了(其实还是个矩形,只是绘画区域在你所裁剪的区域),然后在里面实现水波纹就哦的K了;完整的绘制代码如下:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //裁剪画布为圆形 Path circlePath = new Path(); 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); int j = 1; //循环绘制正弦曲线 循环一次半个周期 for (int i = 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(); }



    推荐阅读