Android自定義WaveProgressView實(shí)現(xiàn)水波紋加載需求
先看效果圖:

你可以定義成你項目的logo圖片,可以設(shè)置水波顏色、波長、波寬、字體大小、顏色、進(jìn)度條的最大值,當(dāng)前進(jìn)度值,還可以設(shè)置波紋震動的快慢。當(dāng)設(shè)置一個進(jìn)度不變的時候,打開時還有一個動畫填滿的效果(比如第二個流量顯示,這里圖片沒有截出這個效果)。
1. 如何使用
1.1 在布局文件中
添加自定義控件:
<cn.fanrunqi.waveprogressview.WaveProgressView android:id="@+id/waveProgressbar" android:background="@drawable/circle" <!--android:background="@drawable/bg_a"--> android:layout_width="130dp" android:layout_height="130dp" />
說明,這里的android:background定義的是控件的形狀,比如上面的圓形和美女,你可用shape.xml定義形狀圖片。
比如,這是一個圓
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="#DDDDDD"/> <size android:width="150dp" android:height="150dp"/> </shape>
也可以直接給android:background設(shè)置一張圖片,比如:
這里注意透明像素,還有為了圖片縮放的時候不變形,建議背景(不管是圖片還是圖形)為正方形。
1.2 在代碼中
你可以選擇進(jìn)行如下設(shè)置:
//設(shè)置當(dāng)前進(jìn)度值和當(dāng)前顯示的文字 waveProgressbar.setCurrent(int currentProgress,String currentText); // 77, "788M/1024M" //設(shè)置進(jìn)度條的最大值 waveProgressbar.setMaxProgress(int maxProgress); //設(shè)置顯示文字的大小和顏色 waveProgressbar.setText(String mTextColor,int mTextSize);//"#FFFF00", 41 //設(shè)置水波的顏色 waveProgressbar.setWaveColor(String mWaveColor); //"#5b9ef4" //設(shè)置波浪的高度和波浪的寬度(均為一個波峰的大小) waveProgressbar.setWave(float mWaveHight,float mWaveWidth); //設(shè)置波浪的上下震動的速度(這里注意值越大,震動的越小) waveProgressbar.setmWaveSpeed(int mWaveSpeed);//The larger the value, the slower the vibration
2. 代碼實(shí)現(xiàn)
這里實(shí)現(xiàn)主要用到的知識有 自定義view、PorterDuffXfermode和二階貝塞爾曲線,不太清楚的可以在我博客找找,都有的?! ?
首先自定義WaveProgressView繼承View,在構(gòu)造函數(shù)中獲取布局文件中設(shè)置的背景,同時設(shè)置一個畫波浪的畫筆和畫文字的畫筆?! ?/p>
private void Init() {
/**
* 獲得背景
*/
if(null==getBackground()){
throw new IllegalArgumentException(String.format("background is null."));
}else{
backgroundBitmap = getBitmapFromDrawable(getBackground());
}
/**
* 波浪畫筆
*/
mPath = new Path();
mPathPaint = new Paint();
mPathPaint.setAntiAlias(true);
mPathPaint.setStyle(Paint.Style.FILL);
/**
* 進(jìn)度畫筆
*/
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setTextAlign(Paint.Align.CENTER);
//開始不斷自我繪制,讓波浪動起來
handler.sendEmptyMessageDelayed(INVALIDATE,100);
}
復(fù)寫onDraw方法,先把波浪畫在畫布上,然后畫背景(給背景畫筆設(shè)置PorterDuff.Mode.DST_ATOP模式:取上層非交集部分與下層交集部分 )。當(dāng)然也可以是PorterDuff.Mode.SRC_ATOP,主要取決于你畫的先后順序。最后把文字畫上去,形成一個最終Bitmap,最后把這個Bitmap畫到onDraw的參數(shù)canvas上。
Paint paint = new Paint();
paint.setAntiAlias(true);
Bitmap finalBmp = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
/**
* 產(chǎn)生一個同樣大小的畫布
*/
Canvas canvas = new Canvas(finalBmp);
/**
* 繪制波浪
*/
float CurMidY = height*(maxProgress-currentProgress)/maxProgress;
if(CurY>CurMidY){
CurY = CurY - (CurY-CurMidY)/10;
}
mPath.reset();
mPath.moveTo(0-distance,CurY);
int waveNum = width/((int)mWaveHalfWidth*4)+1;
int multiplier = 0;
for(int i =0;i<waveNum;i++){
mPath.quadTo(mWaveHalfWidth*(multiplier+1)-distance,CurY-mWaveHight,mWaveHalfWidth*(multiplier+2)-distance,CurY);
mPath.quadTo(mWaveHalfWidth*(multiplier+3)-distance,CurY+mWaveHight,mWaveHalfWidth*(multiplier+4)-distance,CurY);
multiplier+=4;
}
distance +=mWaveHalfWidth/mWaveSpeed;
distance = distance%(mWaveHalfWidth*4);
mPath.lineTo(width,height);
mPath.lineTo(0,height);
mPath.close();
canvas.drawPath(mPath, mPathPaint);
/**
* 對圖片給進(jìn)行縮放
*/
int min = Math.min(width,height);
backgroundBitmap = Bitmap.createScaledBitmap(backgroundBitmap,min,min,false);
/**
* 使用DST_ATOP,取上層非交集部分與下層交集部分 。
*/
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
/**
* 繪制圖片
*/
canvas.drawBitmap(backgroundBitmap,0,0,paint);
/**
* 繪制進(jìn)度文字
*/
canvas.drawText(currentText, width/2, height/2, mTextPaint);
return finalBmp;
這里的CurY是上次波浪中線的y軸坐標(biāo),CurMidY 是當(dāng)前的Y軸坐標(biāo),每次波浪上升的時候?yàn)榱瞬划a(chǎn)生卡頓效果,把這1/100的上升分為10次來繪制。
distance是x軸的偏移量,為了使水波動起來,每次繪制時都要向左進(jìn)行一段偏移?!?/p>
distance +=mWaveHalfWidth/mWaveSpeed; distance = distance%(mWaveHalfWidth*4);
每次偏移距離為 半波寬度/波浪震動速度,因?yàn)橐粋€波是4個半波寬度形成一個循環(huán),然后又回到最開始x位置開始循環(huán)位移。
根據(jù)view的寬度計算出一共要繪制多少個波形出來,同時多加一個波為了向左平移。
int waveNum = width/((int)mWaveHalfWidth*4)+1;
int multiplier = 0;
for(int i =0;i<waveNum;i++){
mPath.quadTo(mWaveHalfWidth*(multiplier+1)-distance,CurY-mWaveHight,mWaveHalfWidth*(multiplier+2)-distance,CurY);
mPath.quadTo(mWaveHalfWidth*(multiplier+3)-distance,CurY+mWaveHight,mWaveHalfWidth*(multiplier+4)-distance,CurY);
multiplier+=4;
}
每次繪制以波形的左邊點(diǎn)、波形的右邊點(diǎn)、view的左下角、view的右下角、形成一個圖片把它繪制到內(nèi)存中新建的和view同大小的canvas上?!?/p>
mPath.reset(); mPath.moveTo(0-distance,CurY); mPath.lineTo(width,height); mPath.lineTo(0,height); mPath.close(); canvas.drawPath(mPath, mPathPaint);
先對背景圖形進(jìn)行縮放再繪制到canvas上,這里的縮放是按最小邊進(jìn)行縮放。
int min = Math.min(width,height); backgroundBitmap = Bitmap.createScaledBitmap(backgroundBitmap,min,min,false);
最后把文字繪制上去,注意我們在初始化中設(shè)置了畫筆,為了能通過代碼設(shè)置文字的顏色,要把設(shè)置文字畫筆顏色和大小放在onDraw方法中。
mPathPaint.setColor(Color.parseColor(mWaveColor)); mTextPaint.setColor(Color.parseColor(mTextColor)); mTextPaint.setTextSize(mTextSize); canvas.drawText(currentText, width/2, height/2, mTextPaint);
為了使波浪動起來,使用handler循環(huán)調(diào)用invalidate刷新界面。同時應(yīng)該在構(gòu)造函數(shù)打開handler循環(huán)。
private static final int INVALIDATE = 0X777;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case INVALIDATE:
invalidate();
sendEmptyMessageDelayed(INVALIDATE,RefreshGap);
break;
}
}
};
最后就是一些相關(guān)屬性設(shè)置的函數(shù)。
/**
* @param currentProgress 當(dāng)前進(jìn)度
* @param currentText 當(dāng)前顯示的進(jìn)度文字
*/
public void setCurrent(int currentProgress,String currentText) {
this.currentProgress = currentProgress;
this.currentText = currentText;
}
/**
* @param maxProgress 設(shè)置進(jìn)度條的最大值,默認(rèn)100
*/
public void setMaxProgress(int maxProgress){
this.maxProgress = maxProgress;
}
/**
* @param mTextColor 文字的顏色
* @param mTextSize 文字的大小
*/
public void setText(String mTextColor,int mTextSize){
this.mTextColor = mTextColor;
this.mTextSize = mTextSize;
}
/**
* @param mWaveHight 波峰的高度
* @param mWaveWidth 一個波峰的寬度
*/
public void setWave(float mWaveHight,float mWaveWidth){
this.mWaveHight = mWaveHight;
this.mWaveHalfWidth = mWaveWidth/2;
}
/**
* @param mWaveColor 水的顏色
*/
public void setWaveColor(String mWaveColor){
this.mWaveColor = mWaveColor;
}
/**
* 值越大震蕩的越慢
* @param mWaveSpeed
*/
public void setmWaveSpeed(int mWaveSpeed){
this.mWaveSpeed = mWaveSpeed;
}
實(shí)現(xiàn)還是比較簡單的,源碼和demo都在上面的地址中,如果有什么問題可以給我留言,謝謝!
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android水波紋載入控件CircleWaterWaveView使用詳解
- android自定義WaveView水波紋控件
- Android自定義View控件實(shí)現(xiàn)多種水波紋漣漪擴(kuò)散效果
- Android自定義View實(shí)現(xiàn)水波紋效果
- Android自定義View實(shí)現(xiàn)水波紋引導(dǎo)動畫
- Android 自定義view實(shí)現(xiàn)水波紋動畫效果
- Android自定義View 實(shí)現(xiàn)水波紋動畫引導(dǎo)效果
- Android自定義view實(shí)現(xiàn)水波紋進(jìn)度球效果
- Android項目實(shí)戰(zhàn)手把手教你畫圓形水波紋loadingview
- Android自定義View實(shí)現(xiàn)簡單水波紋效果
相關(guān)文章
Android開發(fā)中匿名設(shè)備標(biāo)識符OAID使用及初始化
這篇文章主要為大家介紹了Android開發(fā)中匿名設(shè)備標(biāo)識符OAID使用及初始化,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04
Android 如何實(shí)現(xiàn)彈窗順序&優(yōu)先級控制
這篇文章主要介紹了Android 如何實(shí)現(xiàn)彈窗順序&優(yōu)先級控制,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下2021-03-03
Android實(shí)現(xiàn)中國象棋游戲(局域網(wǎng)版)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)局域網(wǎng)版的中國象棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-05-05
Android中替換WebView加載網(wǎng)頁失敗時的頁面
這篇文章主要介紹了Android中替換WebView加載網(wǎng)頁失敗時的頁面,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2017-01-01
Android學(xué)習(xí)之Span的使用方法詳解
這篇文章主要為大家詳細(xì)介紹了Android中各種Span類的使用方法,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Android有一定的幫助,需要的可以參考一下2022-06-06

