通过自定义view实现了一个水滴滴落到水波面,溅起水花并且水波流动上涨的进度条控件。之前看到过好多水波流动的进度条,感觉欠缺些东西,就想到了水滴到水平面,溅起水花然后水流动上涨的进度条效果,于是自己动手写了出来。效果如下,视频录制有些卡顿,实际会流畅很多。
一.用法
1.布局文件中添加WaveProgressView,circleColor属性为圆环颜色,waterColor属性为水波水滴的颜色,progress属性为初始的进度
<com.yhongm.wave_progress_view.WaveProgressView android:id="@+id/wave_progress_view" android:layout_width="300dp" android:layout_height="300dp" android:layout_centerInParent="true" app:circleColor="#e38854" app:progress="0" app:waterColor="#5488e3" />
2.WaveProgressView.setProgress()方法设置当前的进度
二.本文实现的逻辑
1,画水波流动,通过三阶贝塞尔曲线画波形,通过不断的改变waveOffsetX和waveOffsetY的值实现流动的效果
/** * 生成水波流动 * * @param begin 水波形开始的位置 * @param waveLength 水波的长度 * @param waveOffsetX 水波水平的偏移 * @param waveOffsetY 水波垂直方向的偏移 * @return */ private Path getWavePath(float begin, int waveLength, int waveOffsetX, int waveOffsetY) { Path mPath = new Path(); mPath.reset(); mPath.moveTo(waveLength * begin, mCurrentHeight); for (int i = 0; i < mWaveCount; i++) { mPath.quadTo(waveLength * (begin + 0.25f) + (i * waveLength) + waveOffsetX, mCurrentHeight + waveOffsetY, (waveLength * (begin + 0.5f) + (i * waveLength) + waveOffsetX), mCurrentHeight); mPath.quadTo(waveLength * (begin + 0.75f) + (i * waveLength) + waveOffsetX, mCurrentHeight - waveOffsetY, (waveLength * (begin + 1f) + (i * waveLength) + waveOffsetX), mCurrentHeight); } mPath.lineTo(mWidth, mHeight); mPath.lineTo(0, mHeight); mPath.close(); return mPath; }
2.画水滴的形状,水滴的形状是通过一个三角形和一个弧形组成的
/** * 水滴的Path * * @param x 水滴坐标x * @param y 水滴坐标y * @param size 水滴尺寸 * @return */ private Path waterDrop(float x, float y, int size) { Path mDropPath = new Path(); mDropPath.moveTo(x - size, y); mDropPath.lineTo(x, (float) (y - size * 2.5)); mDropPath.lineTo(x + size, y); mDropPath.addArc(x - size, y - size, x + size, y + size, 0, 180); return mDropPath; }
3.画水滴滴落到水波的效果,就是沿轴Y轴不断的移动水滴
/** * 根据位置画水滴 * * @param x * @param y * @param canvas */ private void drawDropByLocation(Canvas canvas, int x, int y) { Path mDropPath = waterDrop(x, y, 30); if (y == (mCurrentHeight + 50)) { mDropPaint.setAlpha(0); } canvas.drawPath(mDropPath, mDropPaint); }
4.画最外两侧溅落的水滴,通过三阶贝塞尔曲线模拟左右两侧水滴溅落的路径,随机生成的水滴溅落路径都在这左右两侧内
/** * 画两侧水滴飞溅的效果,并且随机生成水滴 * * @param canvas * @param x * @param y 当前高度 */ private synchronized void drawDropSplash(Canvas canvas, int x, int y) { PathMeasure mLeftPathMeasure = getOnBothSidesOfPathMeasure(x, y, true); PathMeasure mRightPathMeasure = getOnBothSidesOfPathMeasure(x, y, false); float[] mLeftPos = new float[2]; float[] mRightPos = new float[2]; float[] mLeftTan = new float[2]; float[] mRightTan = new float[2]; for (int i = 0; i < 200; i++) { float percent = i / 200f; mLeftPathMeasure.getPosTan(mLeftPathMeasure.getLength() * percent, mLeftPos, mLeftTan); mRightPathMeasure.getPosTan(mRightPathMeasure.getLength() * percent, mRightPos, mRightTan); mLeftHashMapPath.put(Math.round(mLeftPos[1]), mLeftPos[0]); mRightHashMapPath.put(Math.round(mRightPos[1]), mRightPos[0]); } if (mRandomHashMap.isEmpty() && mRandomHashMap.size() == 0) { pushRandomDrag(y); } drawRandomDrag(canvas, x, y, mLeftHashMapPath, mRightHashMapPath); drawOnBothSidesOfWaterDrop(canvas, mLeftPathMeasure); drawOnBothSidesOfWaterDrop(canvas, mRightPathMeasure); }
/** * 产生随机的水滴 * * @param y */ private void pushRandomDrag(int y) { Random r = new Random(); for (int i = 0; i < 20; i++) { int randomY = r.nextInt(y); if (mLeftHashMapPath.containsKey(randomY)) { Float rightValue = mRightHashMapPath.get(randomY); Float leftValue = mLeftHashMapPath.get(randomY); int roundLeftValue = Math.round(leftValue); int roundRightValue = Math.round(rightValue); if (roundRightValue == roundLeftValue) { roundRightValue++; } int roundMinus = Math.round(roundRightValue - roundLeftValue);//左右差值 float randomX = r.nextInt(roundMinus) + mLeftHashMapPath.get(randomY);//左右差值加上最小值,保证随机值在两者之间 mRandomHashMap.put(randomX, randomY); } } }
5.随机生成的水滴沿着三阶贝塞尔曲线移动,形成溅落的效果
/** * 画随机生成水滴溅起 * * @param canvas * @param x * @param y * @param size * @param randomY * @param randomX */ private void drawSmartDropOnPath(Canvas canvas, int x, int y, int size, int randomY, float randomX) { Path smartDropPath = new Path(); smartDropPath.moveTo(x, y + 50); if (x < randomX) { smartDropPath.cubicTo(x, y + 50, randomX + 30, randomY - 20, randomX, randomY); } else { smartDropPath.cubicTo(x, y + 50, randomX - 30, randomY - 20, randomX, randomY); } smartDropPath.lineTo(randomX, randomY + 150); PathMeasure pathMeasure = new PathMeasure(); pathMeasure.setPath(smartDropPath, false); float[] pos = new float[2]; float[] tan = new float[2]; pathMeasure.getPosTan(pathMeasure.getLength() * mPercent, pos, tan); Path path = waterDrop(pos[0], pos[1], size); canvas.drawPath(path, mSplashPaint); }
完整代码详见 点击打开Github本项目 感兴趣的话帮我点个Star
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍Android自定义view实现水波纹进度球效果,包括了Android自定义view实现水波纹进度球效果的使用技巧和注意事项,需要的朋友参考一下 今天我们要实现的这个view没有太多交互性的view,所以就继承view。 自定义view的套路,套路很深 1、获取我们自定义属性attrs(可省略) 2、重写onMeasure方法,计算控件的宽和高 3
本文向大家介绍Android自定义View实现水波纹效果,包括了Android自定义View实现水波纹效果的使用技巧和注意事项,需要的朋友参考一下 介绍:水波纹散开效果的控件在 App 里面还是比较常见的,例如 网易云音乐歌曲识别,附近搜索场景。 看下实现的效果: 实现思路: 先将最大圆半径与最小圆半径间距分成几等份,从内到外,Paint 透明度依次递减,绘制出同心圆,然后不断的改变这些同心圆的半
本文向大家介绍Android view自定义实现动态进度条,包括了Android view自定义实现动态进度条的使用技巧和注意事项,需要的朋友参考一下 Android 自定义view实现动态进度条 效果图: 这个是看了梁肖的demo,根据他的思路自己写了一个,但是我写的这个貌似计算还是有些问题,从上面的图就可以看出来,左侧、顶部、右侧的线会有被截掉的部分,有懂得希望能给说一下,改进一下,这个
本文向大家介绍Android自定义View实现水平带数字百分比进度条,包括了Android自定义View实现水平带数字百分比进度条的使用技巧和注意事项,需要的朋友参考一下 这个进度条可以反映真实进度,并且完成百分比的文字时随着进度增加而移动的,所在位置也恰好是真实完成的百分比位置,效果如下: 思路如下:第一部分是左侧的蓝色直线,代表已经完成的进度;第二部分是右侧灰色的直线,代表未完成的进度;第三部
本文向大家介绍Android 自定义view实现水波纹动画效果,包括了Android 自定义view实现水波纹动画效果的使用技巧和注意事项,需要的朋友参考一下 在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了个让人兴奋的效果,兴致高昂的来找你,看了之后目的很明确,当然就是希望你能给她; 在这样的关键时候,身子板就一定得硬了,可千万别说不行,爷们儿怎么能说不行呢;
本文向大家介绍Android自定义View实现水波纹引导动画,包括了Android自定义View实现水波纹引导动画的使用技巧和注意事项,需要的朋友参考一下 一、实现效果图 关于贝塞尔曲线 二、实现代码 1.自定义view 2.MainActivity.java 3.activity_main.xml 三、源码下载 http://xiazai.jb51.net/201701/yuanma/Andro