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

最近突然手痒就想搞个贝塞尔曲线做个水波纹效果玩玩,终于功夫不负有心人最后实现了想要的效果,一起来看下吧:

效果图镇楼

0818b9ca8b590ca3270a3433284dd417.png

一:先一步一步来分解一下实现的过程

需要绘制一个正弦曲线(sin)或者余弦曲线(cos)

通过水平平移曲线来的到像水波波动的效果

水平移动的同时还需要有水位上涨,也就是向上平移

裁剪画布为圆形,在圆形区域绘制曲线

通过上面4步就可以实现了

二:现在就来实现第一步,绘制一个sin曲线;这里画了一张图来帮助理解,在PhotoShop中我们绘制一个贝塞尔曲线可以清楚的看到它的控制点如图:

0818b9ca8b590ca3270a3433284dd417.png     

0818b9ca8b590ca3270a3433284dd417.png

绘制贝塞尔曲线我们必须要知道三个点:起点、控制点、终点;有了这三个点我们就可以绘制一段简单二阶贝塞尔曲线。从图中我们可以看出 起点 控制点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);

}

首先肯定是要获取到画布的大小才能确定好起点的坐标,有了起点坐标就可以开始绘制我们的曲线了

在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);

}

经过上面一系例操作一个水波纹效果就出来啦

0818b9ca8b590ca3270a3433284dd417.png

四:接下来就是水平移动这个曲线了为了移动起来更加好看,我们需要在屏幕外面开始绘制一个周期,如下:

//初始化的时候将起点移至屏幕外一个周期

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();

只需要这样就可以产生水波效果了,一起来看效果图吧。

0818b9ca8b590ca3270a3433284dd417.png

五:接下来就是要将画布变成圆形了(其实还是个矩形,只是绘画区域在你所裁剪的区域),然后在里面实现水波纹就哦的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();

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值