Android項(xiàng)目實(shí)戰(zhàn)手把手教你畫(huà)圓形水波紋loadingview
本文實(shí)例講解的是如何畫(huà)一個(gè)滿滿圓形水波紋loadingview,這類(lèi)效果應(yīng)用場(chǎng)景很多,比如內(nèi)存占用百分比之類(lèi)的,分享給大家供大家參考,具體內(nèi)容如下
效果圖如下:

預(yù)備的知識(shí):
- 1.貝塞爾曲線 如果你不了解,可以來(lái)這里進(jìn)行基礎(chǔ)知識(shí)儲(chǔ)備:神奇的貝塞爾曲線
- 2.Paint.setXfermode()以及PorterDuffXfermode
千萬(wàn)不要被這個(gè)b的名字嚇到,不熟悉看到可能會(huì)認(rèn)為很難記,其實(shí) 只要站在巨人的丁丁上 還是很簡(jiǎn)單的。
好了 廢話不多說(shuō) ,跟我一步步來(lái)做一個(gè)炫酷的view吧。
首先給一些屬性,在構(gòu)造器里初始化(不要再ondraw new東西不要再ondraw new東西不要再ondraw new東西不要再ondraw new東西)
//繪制波紋
private Paint mWavePaint;
private PorterDuffXfermode mMode = new PorterDuffXfermode(PorterDuff.Mode.XOR);//設(shè)置mode 為XOR
//繪制圓
private Paint mCirclePaint;
private Canvas mCanvas;//我們自己的畫(huà)布
private Bitmap mBitmap;
private int mWidth;
private int mHeight;
public WaveLoadingView(Context context) {
this(context,null);
}
public WaveLoadingView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public WaveLoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mWavePaint = new Paint();
mWavePaint.setColor(Color.parseColor("#33b5e5"));
mCirclePaint = new Paint();
mCirclePaint.setColor(Color.parseColor("#99cc00"));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY) {
mWidth = widthSize;
}
if (heightMode == MeasureSpec.EXACTLY) {
mHeight = heightSize;
}
setMeasuredDimension(mWidth, mHeight);
mBitmap = Bitmap.createBitmap(300,300, Bitmap.Config.ARGB_8888); //生成一個(gè)bitmap
mCanvas = new Canvas(mBitmap);//講bitmp放在我們自己的畫(huà)布上,實(shí)際上mCanvas.draw的時(shí)候 改變的是這個(gè)bitmap對(duì)象
}
然后,我們給他繪制一點(diǎn)東西,用來(lái)介紹PorterDuffXfermode
@Override
protected void onDraw(Canvas canvas) {
mCanvas.drawCircle(100,100,50,mCirclePaint);
mCanvas.drawRect(100,100,200,200,mWavePaint);
canvas.drawBitmap(mBitmap,0,0,null);
super.onDraw(canvas);
}
嗯,可以看到 是我們現(xiàn)在自己的畫(huà)布上鋪了一個(gè)bitmap(這里可以理解canvas為桌子 bitmap為畫(huà)紙,我們?cè)赽imap上畫(huà)畫(huà)), 然后在bitmap上畫(huà)了 一個(gè)圓,和一個(gè)矩形。最后把我們的mBitmap畫(huà)到系統(tǒng)的畫(huà)布上(顯示到屏幕上),得到了以下效果。
然后我們用setXfermode()方法給他設(shè)置一個(gè)mode,這里設(shè)置XOR。

可以發(fā)現(xiàn)! 相交的地方消失了! 是不是很神奇。
在改一個(gè)mode 試試
private PorterDuffXfermode mMode = new PorterDuffXfermode(PorterDuff.Mode.DST_OVER);

可以看到圓形跑到了矩形上面來(lái)。然后巨人給我們總結(jié)各個(gè)模式如了下圖,這里給一個(gè)說(shuō)明dst為先畫(huà)的 src為后畫(huà)的:.

大家可以根據(jù)這個(gè)規(guī)律試一下。
現(xiàn)在,我們把圓和矩形重疊。模式去掉。
protected void onDraw(Canvas canvas) {
//dst
mCanvas.drawCircle(150,150,50,mCirclePaint);
/ mWavePaint.setXfermode(mMode);
//src
mCanvas.drawRect(100,100,200,200,mWavePaint);
canvas.drawBitmap(mBitmap,0,0,null);
super.onDraw(canvas);
}
我的圓怎么沒(méi)了。。 其實(shí)圓是被覆蓋掉了。 然后我們想實(shí)現(xiàn)一個(gè)效果,就是在圓的范圍內(nèi),顯示矩形的內(nèi)容,該怎么做呢。自己照著圖找找吧哈哈。
我們要實(shí)現(xiàn)的是一個(gè)圓形的水波紋那種loadingview。。首要就是實(shí)現(xiàn)這個(gè)水波紋。
這時(shí)候貝塞爾曲線就派上用場(chǎng)了。這里采用三階貝塞爾, 不停地改變X 模擬水波效果。
if (x > 50) {
isLeft = true;
} else if (x < 0) {
isLeft = false;
}
<span style="white-space:pre"> </span>if (y > -50) { //大于-50是因?yàn)檩o助點(diǎn)是50 為了讓他充滿整個(gè)屏幕
y--;
} if (isLeft) {
x = x - 1;
} else {
x = x + 1;
}
mPath.reset();
mPath.moveTo(0, y);
mPath.cubicTo(100 + x*2, 50 + y, 100 + x*2, y-50, mWidth, y);//前兩個(gè)參數(shù)是輔助點(diǎn)
mPath.lineTo(mWidth, mHeight);//充滿整個(gè)畫(huà)布
mPath.lineTo(0, mHeight);//充滿整個(gè)畫(huà)布
mPath.close();
之后用mCanvas來(lái)繪制這個(gè)bitmap,要注意的是 繪制之前要清空mBitmap,不然path會(huì)重疊
mBitmap.eraseColor(Color.parseColor("#00000000"));
//dst
mCanvas.drawPath(mPath, mPaint);
canvas.drawBitmap(mBitmap, 0, 0, null);
postInvalidateDelayed(10);
哈,水波效果出來(lái)了。接著想辦法讓他畫(huà)到一個(gè)圓形中。 首先繪制一個(gè)圓
mCanvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, mSRCPaint);
現(xiàn)在讓我們回到剛才的問(wèn)題,如何在dst的范圍內(nèi)繪制src呢。答案是:SRC_IN 你找對(duì)了嗎?添加模式
//dst mCanvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2, mSRCPaint); mPaint.setXfermode(mMode); //src mCanvas.drawPath(mPath, mPaint); canvas.drawBitmap(mBitmap, 0, 0, null);
是不是有點(diǎn)感覺(jué)了。如果不這樣做 就需要考慮好多問(wèn)題。動(dòng)態(tài)計(jì)算沿著圓弧x,y坐標(biāo)計(jì)算arcTo的范圍。
完善一下,添加一個(gè)percent來(lái)代表進(jìn)度,讓y來(lái)根據(jù)percent動(dòng)態(tài)改變
y = (int) ((1-mPercent /100f) *mHeight);
添加setPercent方法
public void setPercent(int percent){
mPercent = percent;
}
畫(huà)上百分比的文字。
String str = mPercent + "%";
float txtLength = mTextPaint.measureText(str);
canvas.drawText(mPercent + "%", mWidth / 2-txtLength/2, mHeight / 2, mTextPaint);
然后配合seekBar,最后改改字體大小 畫(huà)筆透明度。 添加個(gè)背景圖 就成了效果圖上的效果。
是不是很有趣,大家可以動(dòng)手實(shí)現(xiàn)一下!
- Android水波紋載入控件CircleWaterWaveView使用詳解
- android自定義WaveView水波紋控件
- Android自定義View控件實(shí)現(xiàn)多種水波紋漣漪擴(kuò)散效果
- Android自定義WaveProgressView實(shí)現(xiàn)水波紋加載需求
- Android自定義View實(shí)現(xiàn)水波紋效果
- Android自定義View實(shí)現(xiàn)水波紋引導(dǎo)動(dòng)畫(huà)
- Android 自定義view實(shí)現(xiàn)水波紋動(dòng)畫(huà)效果
- Android自定義View 實(shí)現(xiàn)水波紋動(dòng)畫(huà)引導(dǎo)效果
- Android自定義view實(shí)現(xiàn)水波紋進(jìn)度球效果
- Android自定義View實(shí)現(xiàn)簡(jiǎn)單水波紋效果
相關(guān)文章
Android開(kāi)發(fā)之設(shè)置開(kāi)機(jī)自動(dòng)啟動(dòng)的幾種方法
這篇文章主要介紹了Android開(kāi)發(fā)之設(shè)置開(kāi)機(jī)自動(dòng)啟動(dòng)的幾種方法的相關(guān)資料,這里提供三種方法幫助大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-08-08
EditText實(shí)現(xiàn)輸入限制和校驗(yàn)功能實(shí)例代碼
本文通過(guò)實(shí)例代碼給大家介紹EditText實(shí)現(xiàn)輸入限制和校驗(yàn)功能,感興趣的朋友參考下吧2017-08-08
詳解AndroidStudio JNI +Gradle3.0以上JNI爬坑之旅
這篇文章主要介紹了詳解AndroidStudio JNI +Gradle3.0以上JNI爬坑之旅,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12
深入Android Handler,MessageQueue與Looper關(guān)系
這篇文章主要介紹了深入Android Handler,MessageQueue與Looper關(guān)系,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-08-08
Kotlin語(yǔ)言使用BroadcastReceiver示例介紹
Android開(kāi)發(fā)的四大組件分別是:活動(dòng)(activity),用于表現(xiàn)功能;服務(wù)(service),后臺(tái)運(yùn)行服務(wù),不提供界面呈現(xiàn);廣播接受者(Broadcast Receive),勇于接收廣播;內(nèi)容提供者(Content Provider),支持多個(gè)應(yīng)用中存儲(chǔ)和讀取數(shù)據(jù),相當(dāng)于數(shù)據(jù)庫(kù),本篇著重介紹廣播組件2022-09-09
6步輕松實(shí)現(xiàn)兩個(gè)listView聯(lián)動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了教大家通過(guò)6步輕松實(shí)現(xiàn)兩個(gè)listView聯(lián)動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
Flutter利用ORM框架簡(jiǎn)化本地?cái)?shù)據(jù)庫(kù)管理詳解
使用?sqflite?相對(duì)來(lái)說(shuō)還是有點(diǎn)復(fù)雜,比如遇到數(shù)據(jù)不兼容的時(shí)候需要手動(dòng)轉(zhuǎn)換,增加了不少繁瑣的代碼。本篇我們就來(lái)介紹一個(gè)?ORM?框架,來(lái)簡(jiǎn)化數(shù)據(jù)庫(kù)的管理,感興趣的可以了解一下2023-04-04
android控件Banner實(shí)現(xiàn)簡(jiǎn)單輪播圖效果
這篇文章主要為大家詳細(xì)介紹了android控件Banner實(shí)現(xiàn)簡(jiǎn)單輪播圖效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05
詳解Android SpannableString多行圖文混排的應(yīng)用實(shí)戰(zhàn)
本篇文章主要介紹了Android SpannableString多行圖文混排的應(yīng)用實(shí)戰(zhàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12

