关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

Android自定义view实现水波进度条控件

发布时间:2020-09-21 13:16:43

通过自定义view实现了一个水滴滴落到水波面,溅起水花并且水波流动上涨的进度条控件。之前看到过好多水波流动的进度条,感觉欠缺些东西,就想到了水滴到水平面,溅起水花然后水流动上涨的进度条效果,于是自己动手写了出来。效果如下,视频录制有些卡顿,实际会流畅很多。


一.用法

1.布局文件中添加WaveProgressView,circleColor属性为圆环颜色,waterColor属性为水波水滴的颜色,progress属性为初始的进度

<com.yhongm.wave_progress_view.WaveProgressViewandroid: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的值实现流动的效果

/** * 生成水波流动 * *@parambegin 水波形开始的位置 *@paramwaveLength 水波的长度 *@paramwaveOffsetX 水波水平的偏移 *@paramwaveOffsetY 水波垂直方向的偏移 *@return*/privatePathgetWavePath(floatbegin,intwaveLength,intwaveOffsetX,intwaveOffsetY){ Path mPath =newPath(); mPath.reset(); mPath.moveTo(waveLength * begin, mCurrentHeight);for(inti =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();returnmPath; }

2.画水滴的形状,水滴的形状是通过一个三角形和一个弧形组成的

/** * 水滴的Path * *@paramx 水滴坐标x *@paramy 水滴坐标y *@paramsize 水滴尺寸 *@return*/privatePathwaterDrop(floatx,floaty,intsize){ Path mDropPath =newPath(); 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);returnmDropPath; }

3.画水滴滴落到水波的效果,就是沿轴Y轴不断的移动水滴

/** * 根据位置画水滴 * *@paramx *@paramy *@paramcanvas */privatevoiddrawDropByLocation(Canvas canvas,intx,inty){ Path mDropPath = waterDrop(x, y,30);if(y == (mCurrentHeight +50)) { mDropPaint.setAlpha(0); } canvas.drawPath(mDropPath, mDropPaint); }

4.画最外两侧溅落的水滴,通过三阶贝塞尔曲线模拟左右两侧水滴溅落的路径,随机生成的水滴溅落路径都在这左右两侧内

/** * 画两侧水滴飞溅的效果,并且随机生成水滴 * *@paramcanvas *@paramx *@paramy 当前高度 */privatesynchronizedvoiddrawDropSplash(Canvas canvas,intx,inty){ PathMeasure mLeftPathMeasure = getOnBothSidesOfPathMeasure(x, y,true); PathMeasure mRightPathMeasure = getOnBothSidesOfPathMeasure(x, y,false);float[] mLeftPos =newfloat[2];float[] mRightPos =newfloat[2];float[] mLeftTan =newfloat[2];float[] mRightTan =newfloat[2];for(inti =0; i <200; i++) {floatpercent = 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 */privatevoidpushRandomDrag(inty){ Random r =newRandom();for(inti =0; i <20; i++) {intrandomY = r.nextInt(y);if(mLeftHashMapPath.containsKey(randomY)) { Float rightValue = mRightHashMapPath.get(randomY); Float leftValue = mLeftHashMapPath.get(randomY);introundLeftValue = Math.round(leftValue);introundRightValue = Math.round(rightValue);if(roundRightValue == roundLeftValue) { roundRightValue++; }introundMinus = Math.round(roundRightValue - roundLeftValue);//左右差值floatrandomX = r.nextInt(roundMinus) + mLeftHashMapPath.get(randomY);//左右差值加上最小值,保证随机值在两者之间mRandomHashMap.put(randomX, randomY); } } }

5.随机生成的水滴沿着三阶贝塞尔曲线移动,形成溅落的效果

/** * 画随机生成水滴溅起 * *@paramcanvas *@paramx *@paramy *@paramsize *@paramrandomY *@paramrandomX */privatevoiddrawSmartDropOnPath(Canvas canvas,intx,inty,intsize,intrandomY,floatrandomX){ Path smartDropPath =newPath(); 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 =newPathMeasure(); pathMeasure.setPath(smartDropPath,false);float[] pos =newfloat[2];float[] tan =newfloat[2]; pathMeasure.getPosTan(pathMeasure.getLength() * mPercent, pos, tan); Path path = waterDrop(pos[0], pos[1], size); canvas.drawPath(path, mSplashPaint); }

完整代码详见 点击打开Github本项目 感兴趣的话帮我点个Star

以上就是本文的全部内容,喜欢的可以常看 西昆云




/template/Home/Zkeys2/PC/Static