Android如何自定義View實現橫向的雙水波紋進度條
網上垂直的水波紋進度條很多,但橫向的很少,將垂直的水波紋改為水平的還遇到瞭些麻煩,現在完善後發佈出來,希望遇到的人少躺點坑。
思路分析
整體效果可分為三個,繪制圓角背景和圓角矩形,繪制第一條和第二條水波浪,根據自定義進度變化效果。
功能實現
1.繪制圓角背景和圓角矩形邊框
圓角矩形邊框:
private RectF rectBorder; if (rectBorder == null) { rectBorder = new RectF(0.5f * dp1, 0.5f * dp1, waveActualSizeWidth - 0.5f * dp1, waveActualSizeHeight - 0.5f * dp1); } canvas.drawRoundRect(rectBorder, dp27, dp27, borderPaint);
我們創建一個新的畫佈,然後在畫佈裡畫上圓角矩形背景和第一條和第二條水波浪:
//這裡用到瞭緩存 根據參數創建新位圖 if (circleBitmap == null) { circleBitmap = Bitmap.createBitmap(waveActualSizeWidth, waveActualSizeHeight, Bitmap.Config.ARGB_8888); } //以該bitmap為底創建一塊畫佈 if (bitmapCanvas == null) { bitmapCanvas = new Canvas(circleBitmap); } // 圓角矩形背景,為瞭能讓波浪填充完整個圓形背景 if (rectBg == null) { rectBg = new RectF(0, 0, waveActualSizeWidth, waveActualSizeHeight); } bitmapCanvas.drawRoundRect(rectBg, dp27, dp27, backgroundPaint); //裁剪圖片 canvas.drawBitmap(circleBitmap, 0, 0, null);
2.通過貝塞爾曲線實現雙水波
1)實現第一條水波
/** * 繪制波浪線 */ private Path canvasWavePath() { //要先清掉路線 wavePath.reset(); //起始點移至(0,0) p0 -p1 的高度隨著進度的變化而變化 wavePath.moveTo((currentPercent) * waveActualSizeWidth, -moveDistance); //最多能繪制多少個波浪 //其實也可以用 i < getWidth() ;i+=waveLength來判斷 這個沒那麼完美 //繪制p0 - p1 繪制波浪線 這裡有一段是超出View的,在View右邊距的右邊 所以是* 2 for (int i = 0; i < waveNumber * 2; i++) { wavePath.rQuadTo(waveHeight, waveLength / 2, 0, waveLength); wavePath.rQuadTo(-waveHeight, waveLength / 2, 0, waveLength); } //連接p1 - p2 wavePath.lineTo(0, waveActualSizeHeight); //連接p2 - p0 wavePath.lineTo(0, 0); //封閉起來填充 wavePath.close(); return wavePath; }
moveDistance為水波垂直方向移動的距離。
waveLength為水波長度,一個上弧加一個下弧為一個波長。
path的起始點為(0,0)可根據進度動態改變,然後循環畫曲線,長度是有幾個波浪就是多長,然後連接到view高度的位置,最後到(0,0),形成一個封閉的區域,這樣就實現瞭一個填充的水波效果。
2)繪制第二條水波,第二條水波和第一條類似,隻是起始點變瞭:
/** * 繪制第二層波浪 */ private Path canvasSecondPath() { secondWavePath.reset(); //初始點移動到下方 secondWavePath.moveTo((currentPercent) * waveActualSizeWidth, waveActualSizeHeight + moveDistance); for (int i = 0; i < waveNumber * 2; i++) { secondWavePath.rQuadTo(waveHeight, -waveLength / 2, 0, -waveLength); secondWavePath.rQuadTo(-waveHeight, -waveLength / 2, 0, -waveLength); } secondWavePath.lineTo(0, 0); secondWavePath.lineTo(0, waveActualSizeHeight); secondWavePath.close(); return secondWavePath; }
3.設置動畫使進度和水波紋變化
/** * 設置進度 * * @param currentProgress 進度 * @param duration 達到進度需要的時間 */ public void setProgress(int currentProgress, long duration, AnimatorListenerAdapter listenerAdapter) { float percent = currentProgress * 1f / maxProgress; this.currentProgress = currentProgress; //從0開始變化 currentPercent = 0; moveDistance = 0; mProgressAnimator = ValueAnimator.ofFloat(0, percent); //設置動畫時間 mProgressAnimator.setDuration(duration); //讓動畫勻速播放,避免出現波浪平移停頓的現象 mProgressAnimator.setInterpolator(new LinearInterpolator()); mProgressAnimator.addUpdateListener(listener); mProgressAnimator.addListener(listenerAdapter); mProgressAnimator.start(); // 波浪線 startWaveAnimal(); } /** * 波浪動畫 */ private void startWaveAnimal() { //動畫實例化 if (waveProgressAnimator == null) { waveProgressAnimator = new WaveProgressAnimal(); //設置動畫時間 waveProgressAnimator.setDuration(2000); //設置循環播放 waveProgressAnimator.setRepeatCount(Animation.INFINITE); //讓動畫勻速播放,避免出現波浪平移停頓的現象 waveProgressAnimator.setInterpolator(new LinearInterpolator()); //當前視圖開啟動畫 this.startAnimation(waveProgressAnimator); } }
其中波浪動畫是通過改變moveDistance的值改變縱坐標達到,進度主要是通過改變百分比currentPercent改變波浪的橫坐標達到。
結語
通過這個項目,主要可以學到貝塞爾曲線,也可以搭配上不同的動畫,搞定產品的各種交互效果。對應的文件:HorizontalWaveProgressView.java
到此這篇關於Android如何自定義View實現橫向的雙水波紋進度條的文章就介紹到這瞭,更多相關Android自定義進度條內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- SK電信與亞馬遜雲合作,在韓國推出瞭首個5G邊緣雲服務
- Android自定義View實現球形動態加速球
- Unity Shader實現3D翻頁效果
- Android自定義View實現圓弧進度的效果
- Android自定義view仿QQ的Tab按鈕動畫效果(示例代碼)