通過(guò)自定義view實(shí)現(xiàn)了一個(gè)水滴滴落到水波面,濺起水花并且水波流動(dòng)上漲的進(jìn)度條控件。之前看到過(guò)好多水波流動(dòng)的進(jìn)度條,感覺(jué)欠缺些東西,就想到了水滴到水平面,濺起水花然后水流動(dòng)上漲的進(jìn)度條效果,于是自己動(dòng)手寫(xiě)了出來(lái)。效果如下,視頻錄制有些卡頓,實(shí)際會(huì)流暢很多。
創(chuàng)新互聯(lián)專(zhuān)注于企業(yè)成都全網(wǎng)營(yíng)銷(xiāo)推廣、網(wǎng)站重做改版、亳州網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5高端網(wǎng)站建設(shè)、商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為亳州等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。
一.用法
1.布局文件中添加WaveProgressView,circleColor屬性為圓環(huán)顏色,waterColor屬性為水波水滴的顏色,progress屬性為初始的進(jìn)度
2.WaveProgressView.setProgress()方法設(shè)置當(dāng)前的進(jìn)度
二.本文實(shí)現(xiàn)的邏輯
1,畫(huà)水波流動(dòng),通過(guò)三階貝塞爾曲線畫(huà)波形,通過(guò)不斷的改變waveOffsetX和waveOffsetY的值實(shí)現(xiàn)流動(dòng)的效果
/** * 生成水波流動(dòng) * * @param begin 水波形開(kāi)始的位置 * @param waveLength 水波的長(zhǎng)度 * @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.畫(huà)水滴的形狀,水滴的形狀是通過(guò)一個(gè)三角形和一個(gè)弧形組成的
/** * 水滴的Path * * @param x 水滴坐標(biāo)x * @param y 水滴坐標(biāo)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.畫(huà)水滴滴落到水波的效果,就是沿軸Y軸不斷的移動(dòng)水滴
/** * 根據(jù)位置畫(huà)水滴 * * @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.畫(huà)最外兩側(cè)濺落的水滴,通過(guò)三階貝塞爾曲線模擬左右兩側(cè)水滴濺落的路徑,隨機(jī)生成的水滴濺落路徑都在這左右兩側(cè)內(nèi)
/** * 畫(huà)兩側(cè)水滴飛濺的效果,并且隨機(jī)生成水滴 * * @param canvas * @param x * @param y 當(dāng)前高度 */ 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); }
/** * 產(chǎn)生隨機(jī)的水滴 * * @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);//左右差值加上最小值,保證隨機(jī)值在兩者之間 mRandomHashMap.put(randomX, randomY); } } }
5.隨機(jī)生成的水滴沿著三階貝塞爾曲線移動(dòng),形成濺落的效果
/** * 畫(huà)隨機(jī)生成水滴濺起 * * @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); }
完整代碼詳見(jiàn) 點(diǎn)擊打開(kāi)Github本項(xiàng)目 感興趣的話幫我點(diǎn)個(gè)Star
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。