Android如何自定義View實(shí)現(xiàn)橫向的雙水波紋進(jìn)度條
網(wǎng)上垂直的水波紋進(jìn)度條很多,但橫向的很少,將垂直的水波紋改為水平的還遇到了些麻煩,現(xiàn)在完善后發(fā)布出來(lái),希望遇到的人少躺點(diǎn)坑。
思路分析
整體效果可分為三個(gè),繪制圓角背景和圓角矩形,繪制第一條和第二條水波浪,根據(jù)自定義進(jìn)度變化效果。
功能實(shí)現(xiàn)
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);
我們創(chuàng)建一個(gè)新的畫(huà)布,然后在畫(huà)布里畫(huà)上圓角矩形背景和第一條和第二條水波浪:
//這里用到了緩存 根據(jù)參數(shù)創(chuàng)建新位圖
if (circleBitmap == null) {
circleBitmap = Bitmap.createBitmap(waveActualSizeWidth, waveActualSizeHeight, Bitmap.Config.ARGB_8888);
}
//以該bitmap為底創(chuàng)建一塊畫(huà)布
if (bitmapCanvas == null) {
bitmapCanvas = new Canvas(circleBitmap);
}
// 圓角矩形背景,為了能讓波浪填充完整個(gè)圓形背景
if (rectBg == null) {
rectBg = new RectF(0, 0, waveActualSizeWidth, waveActualSizeHeight);
}
bitmapCanvas.drawRoundRect(rectBg, dp27, dp27, backgroundPaint);
//裁剪圖片
canvas.drawBitmap(circleBitmap, 0, 0, null);
2.通過(guò)貝塞爾曲線實(shí)現(xiàn)雙水波
1)實(shí)現(xiàn)第一條水波
/**
* 繪制波浪線
*/
private Path canvasWavePath() {
//要先清掉路線
wavePath.reset();
//起始點(diǎn)移至(0,0) p0 -p1 的高度隨著進(jìn)度的變化而變化
wavePath.moveTo((currentPercent) * waveActualSizeWidth, -moveDistance);
//最多能繪制多少個(gè)波浪
//其實(shí)也可以用 i < getWidth() ;i+=waveLength來(lái)判斷 這個(gè)沒(méi)那么完美
//繪制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);
//封閉起來(lái)填充
wavePath.close();
return wavePath;
}
moveDistance為水波垂直方向移動(dòng)的距離。
waveLength為水波長(zhǎng)度,一個(gè)上弧加一個(gè)下弧為一個(gè)波長(zhǎng)。
path的起始點(diǎn)為(0,0)可根據(jù)進(jìn)度動(dòng)態(tài)改變,然后循環(huán)畫(huà)曲線,長(zhǎng)度是有幾個(gè)波浪就是多長(zhǎng),然后連接到view高度的位置,最后到(0,0),形成一個(gè)封閉的區(qū)域,這樣就實(shí)現(xiàn)了一個(gè)填充的水波效果。
2)繪制第二條水波,第二條水波和第一條類(lèi)似,只是起始點(diǎn)變了:
/**
* 繪制第二層波浪
*/
private Path canvasSecondPath() {
secondWavePath.reset();
//初始點(diǎn)移動(dòng)到下方
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.設(shè)置動(dòng)畫(huà)使進(jìn)度和水波紋變化
/**
* 設(shè)置進(jìn)度
*
* @param currentProgress 進(jìn)度
* @param duration 達(dá)到進(jìn)度需要的時(shí)間
*/
public void setProgress(int currentProgress, long duration, AnimatorListenerAdapter listenerAdapter) {
float percent = currentProgress * 1f / maxProgress;
this.currentProgress = currentProgress;
//從0開(kāi)始變化
currentPercent = 0;
moveDistance = 0;
mProgressAnimator = ValueAnimator.ofFloat(0, percent);
//設(shè)置動(dòng)畫(huà)時(shí)間
mProgressAnimator.setDuration(duration);
//讓動(dòng)畫(huà)勻速播放,避免出現(xiàn)波浪平移停頓的現(xiàn)象
mProgressAnimator.setInterpolator(new LinearInterpolator());
mProgressAnimator.addUpdateListener(listener);
mProgressAnimator.addListener(listenerAdapter);
mProgressAnimator.start();
// 波浪線
startWaveAnimal();
}
/**
* 波浪動(dòng)畫(huà)
*/
private void startWaveAnimal() {
//動(dòng)畫(huà)實(shí)例化
if (waveProgressAnimator == null) {
waveProgressAnimator = new WaveProgressAnimal();
//設(shè)置動(dòng)畫(huà)時(shí)間
waveProgressAnimator.setDuration(2000);
//設(shè)置循環(huán)播放
waveProgressAnimator.setRepeatCount(Animation.INFINITE);
//讓動(dòng)畫(huà)勻速播放,避免出現(xiàn)波浪平移停頓的現(xiàn)象
waveProgressAnimator.setInterpolator(new LinearInterpolator());
//當(dāng)前視圖開(kāi)啟動(dòng)畫(huà)
this.startAnimation(waveProgressAnimator);
}
}
其中波浪動(dòng)畫(huà)是通過(guò)改變moveDistance的值改變縱坐標(biāo)達(dá)到,進(jìn)度主要是通過(guò)改變百分比currentPercent改變波浪的橫坐標(biāo)達(dá)到。
結(jié)語(yǔ)
通過(guò)這個(gè)項(xiàng)目,主要可以學(xué)到貝塞爾曲線,也可以搭配上不同的動(dòng)畫(huà),搞定產(chǎn)品的各種交互效果。對(duì)應(yīng)的文件:HorizontalWaveProgressView.java
到此這篇關(guān)于Android如何自定義View實(shí)現(xiàn)橫向的雙水波紋進(jìn)度條的文章就介紹到這了,更多相關(guān)Android自定義進(jìn)度條內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android實(shí)現(xiàn)水波紋效果實(shí)例代碼
- Android實(shí)現(xiàn)漸變色水波紋效果
- Android 通過(guò)自定義view實(shí)現(xiàn)水波紋效果案例詳解
- Android 自定義球型水波紋帶圓弧進(jìn)度效果(實(shí)例代碼)
- Android實(shí)現(xiàn)水波紋擴(kuò)散效果
- Android實(shí)現(xiàn)水波紋特效
- android實(shí)現(xiàn)簡(jiǎn)單底部導(dǎo)航欄
- Android實(shí)現(xiàn)底部導(dǎo)航欄效果
- Android自定義水波紋底部導(dǎo)航的實(shí)現(xiàn)
相關(guān)文章
Android形狀圖形與狀態(tài)列表圖形及九宮格圖片超詳細(xì)講解
這篇文章主要介紹了Android形狀圖形與狀態(tài)列表圖形及九宮格圖片的應(yīng)用方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-09-09
Android編程實(shí)現(xiàn)打勾顯示輸入密碼功能
這篇文章主要介紹了Android編程實(shí)現(xiàn)打勾顯示輸入密碼功能,涉及Android控件布局及屬性相關(guān)操作技巧,需要的朋友可以參考下2017-02-02
Android 實(shí)現(xiàn)不依賴(lài)焦點(diǎn)和選中的TextView跑馬燈
本文主要介紹Android 跑馬燈的實(shí)現(xiàn),這里提供實(shí)現(xiàn)詳細(xì)實(shí)現(xiàn)代碼供大家參考,有需要的小伙伴可以看下2016-07-07
解決android studio android monitor打不開(kāi)的問(wèn)題
下面小編就為大家分享一篇解決android studio android monitor打不開(kāi)的問(wèn)題,具有很的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Flutter Set存儲(chǔ)自定義對(duì)象時(shí)保證唯一的方法詳解
在Flutter中,Set和List是兩種不同的集合類(lèi)型,List中存儲(chǔ)的元素可以重復(fù),Set中存儲(chǔ)的元素不可重復(fù),如果想在Set中存儲(chǔ)自定義對(duì)象,需要確保對(duì)象的唯一性,那么如何保證唯一,接下來(lái)小編就給大家詳細(xì)的介紹一下2023-11-11
Flutter移動(dòng)端進(jìn)行多渠道打包發(fā)布的全過(guò)程
在使用flutter開(kāi)發(fā)的過(guò)程中,需要根據(jù)不同的環(huán)境,不同的包名來(lái)打包,下面這篇文章主要給大家介紹了關(guān)于Flutter移動(dòng)端進(jìn)行多渠道打包發(fā)布的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06
Android?studio實(shí)現(xiàn)app登錄界面
這篇文章主要為大家詳細(xì)介紹了Android?studio實(shí)現(xiàn)app登錄界面,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04

