日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android自定义水波纹,android 自定义view-水波纹进度球

發布時間:2023/12/19 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android自定义水波纹,android 自定义view-水波纹进度球 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

android 進階之路-自定義view-水波紋進度球

如果你是老司機,一看標題就會就return吧,嘻嘻。

在我們的日常開發中自定義控件還是用的挺多的,設計師或者產品為了更好的漂亮,美觀,交互都會做一些牛逼的ui效果圖,但是最后實現的還是我們程序員啊。

所以說 自定義view你還是得會的。

要開車了哦,請刷卡...

滴,老司機卡

滴,學生卡

滴,...

刷卡

今天我們要實現的這個view沒有太多交互性的view,所以就繼承view

自定義view的套路,套路很深

獲取我們自定義屬性attrs(可省略)

重寫onMeasure方法,計算控件的寬和高

重寫onDraw方法,繪制我們的控件

這么看來,自定義view的套路很清晰嘛。

我們看下今天的效果圖,其中一個是放慢的效果(時間調的長)

效果圖1

效果圖2

我們按照套路來。

一.自定義屬性

看下效果圖我們就知道因該需要哪些屬性。就不說了。

然后就是獲取我們的這些屬性,就是用TypedArray來獲取。當然是在構造中獲取,一般我們會復寫構造方法,少參數調用參數多的,然后走到參數最多的那個。

下面是獲取自定義屬性的代碼:

TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.WaveProgressView, defStyleAttr, R.style.WaveProgressViewDefault);

radius = (int) a.getDimension(R.styleable.WaveProgressView_radius, radius);

textColor = a.getColor(R.styleable.WaveProgressView_progress_text_color, 0);

textSize = a.getDimensionPixelSize(R.styleable.WaveProgressView_progress_text_size, 0);

progressColor = a.getColor(R.styleable.WaveProgressView_progress_color, 0);

radiusColor = a.getColor(R.styleable.WaveProgressView_radius_color, 0);

progress = a.getFloat(R.styleable.WaveProgressView_progress, 0);

maxProgress = a.getFloat(R.styleable.WaveProgressView_maxProgress, 100);

a.recycle();

注: R.style.WaveProgressViewDefault是這個控件的默認樣式。

二.onMeasure測量

我們重寫這個方法主要是根據父控件的寬和高來設置自己的寬和高。

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

//計算寬和高

int exceptW = getPaddingLeft() + getPaddingRight() + 2 * radius;

int exceptH = getPaddingTop() + getPaddingBottom() + 2 * radius;

int width = resolveSize(exceptW, widthMeasureSpec);

int height = resolveSize(exceptH, heightMeasureSpec);

int min = Math.min(width, height);

this.width = this.height = min;

//計算半徑,減去padding的最小值

int minLR = Math.min(getPaddingLeft(), getPaddingRight());

int minTB = Math.min(getPaddingTop(), getPaddingBottom());

minPadding = Math.min(minLR, minTB);

radius = (min - minPadding * 2) / 2;

setMeasuredDimension(min, min);

}

首先該控件的寬和高肯定是一樣的,因為是個圓嘛。其實是寬和高與半徑和內邊距(padding)有關,這里的內邊距,我們取上下左右最小的一個。寬和高也選擇取最小的。

this.width = this.height = min; 包含左右邊距。

resolveSize這個方法很好的為我們實現了我們想要的寬和高我慢看下源碼。

public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {

final int specMode = MeasureSpec.getMode(measureSpec);

final int specSize = MeasureSpec.getSize(measureSpec);

final int result;

switch (specMode) {

case MeasureSpec.AT_MOST:

if (specSize < size) {

result = specSize | MEASURED_STATE_TOO_SMALL;

} else {

result = size;

}

break;

case MeasureSpec.EXACTLY:

result = specSize;

break;

case MeasureSpec.UNSPECIFIED:

default:

result = size;

}

return result | (childMeasuredState & MEASURED_STATE_MASK);

}

如果我們自己寫也是這樣寫。

最后通過setMeasuredDimension設置寬和高。

三.onDraw繪制

關于繪制有很多android 提供了很多API,這里就不多說了。

繪制首先就是一些畫筆的初始化。

需要提一下繪制path路徑的畫筆設置為PorterDuff.Mode.SRC_IN模式,這個模式只顯示重疊的部分。

pathPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

pathPaint.setColor(progressColor);

pathPaint.setDither(true);

pathPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

我們要將所有的繪制 繪制到一個透明的bitmap上,然后將這個bitmap繪制到canvas上。

if (bitmap == null) {

bitmap = Bitmap.createBitmap(this.width, this.height, Bitmap.Config.ARGB_8888);

bitmapCanvas = new Canvas(bitmap);

}

為了方便計算和繪制,我將坐標系平移padding的距離

bitmapCanvas.save();

//移動坐標系

bitmapCanvas.translate(minPadding, minPadding);

// .... some thing

bitmapCanvas.restore();

3.1繪制圓

bitmapCanvas.drawCircle(radius, radius, radius, circlePaint);

3.2繪制PATH 路徑.

一是要實現波紋的左右飄,和上下的振幅慢慢的減小

繪制這個之前我們需要知道二階貝塞爾曲線的大致原理。

簡單的說就是知道:P1起始點,P2是終點,P1是控制點.利用塞爾曲線的公式就可以得道沿途的一些點,最后把點連起來就是嘍。

下面這個圖片來于網絡:

二階貝塞爾曲線

在android-sdk里提供了繪制貝塞爾曲線的函數rQuadTo方法

public void rQuadTo(float dx1, float dy1, float dx2, float dy2)

dx1:控制點X坐標,表示相對上一個終點X坐標的位移坐標,可為負值,正值表示相加,負值表示相減;

dy1:控制點Y坐標,相對上一個終點Y坐標的位移坐標。同樣可為負值,正值表示相加,負值表示相減;

dx2:終點X坐標,同樣是一個相對坐標,相對上一個終點X坐標的位移值,可為負值,正值表示相加,負值表示相減;

dy2:終點Y坐標,同樣是一個相對,相對上一個終點Y坐標的位移值??蔀樨撝?#xff0c;正值表示相加,負值表示相減;

這四個參數都是傳遞的都是相對值,相對上一個終點的位移值。

要實現振幅慢慢的減小我們可以調節控制點的y坐標即可,即:

float percent=progress * 1.0f / maxProgress;

就可以得到[0,1]的

一個閉區間,[0,1]這貨好啊,我喜歡,可以來做很多事情。

這樣我們就可以根據percent來調節控制點的y坐標了。

//根據直徑計算繪制貝賽爾曲線的次數

int count = radius * 4 / 60;

//控制-控制點y的坐標

float point = (1 - percent) * 15;

for (int i = 0; i < count; i++) {

path.rQuadTo(15, -point, 30, 0);

path.rQuadTo(15, point, 30, 0);

}

這里給出一個振幅的原理圖:

振幅

然后就是根據寬來循環周期就可以了

要實現左右波紋只需要控制閉合路徑的左上角的x坐標即可,當然也是根據percent嘍。

大家可以結合下面這個圖來理解下上面的話。

原理圖

path繪制的完整代碼片段。

//繪制PATH

//重置繪制路線

path.reset();

float percent=progress * 1.0f / maxProgress;

float y = (1 - percent) * radius * 2;

//移動到右上邊

path.moveTo(radius * 2, y);

//移動到最右下方

path.lineTo(radius * 2, radius * 2);

//移動到最左下邊

path.lineTo(0, radius * 2);

//移動到左上邊

// path.lineTo(0, y);

//實現左右波動,根據progress來平移

path.lineTo(-(1 -percent) * radius*2, y);

if (progress != 0.0f) {

//根據直徑計算繪制貝賽爾曲線的次數

int count = radius * 4 / 60;

//控制-控制點y的坐標

float point = (1 - percent) * 15;

for (int i = 0; i < count; i++) {

path.rQuadTo(15, -point, 30, 0);

path.rQuadTo(15, point, 30, 0);

}

}

//閉合

path.close();

bitmapCanvas.drawPath(path, pathPaint);

3.3繪制進度的文字

這個就比較簡單了,繪制在控件的中間即可。關于文字的坐標計算還是很好理解的。

//繪制文字

String text = progress + "%";

float textW = textPaint.measureText(text);

Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();

float baseLine = radius - (fontMetrics.ascent + fontMetrics.descent) / 2;

bitmapCanvas.drawText(text, radius - textW / 2, baseLine, textPaint);

最后別忘了把我們的bitmap繪制到canvas上。

canvas.drawBitmap(bitmap, 0, 0, null);

哦,最后是實用方法,這里我們不用thread+handler,我們用屬性動畫。

你懂的!!!,like

ObjectAnimator objectAnimator0 = ObjectAnimator.ofFloat(waveProgressView_0, "progress", 0f, 100f);

objectAnimator0.setDuration(3300);

objectAnimator0.setInterpolator(new LinearInterpolator());

objectAnimator0.start();

總結

以上是生活随笔為你收集整理的android自定义水波纹,android 自定义view-水波纹进度球的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。