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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android自定义表盘部件,Android自定义view仿支付宝芝麻信用表盘

發(fā)布時間:2023/12/2 Android 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android自定义表盘部件,Android自定义view仿支付宝芝麻信用表盘 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

演示效果

實現(xiàn)步驟:

1.畫不同寬度和半徑的內(nèi)外圓弧

2.通過循環(huán)旋轉(zhuǎn)canvas,在固定位置繪制短線刻度,長線刻度,刻度文字

3.繪制view中心幾個文本,并調(diào)整位置

4.實時更新當前旋轉(zhuǎn)角度刷新小圓點位置;

5.判斷分數(shù)應該坐落的區(qū)間,再根據(jù)該區(qū)間的角度比例獲取實際的角度。

6.用ObjectAnimator實現(xiàn)滾動文字

步驟代碼講解:

這里是聲明的變量及常量

/** 圓環(huán)paint */

private Paint ringPaint;

/** 信用分文字paint */

private Paint scoreTextPaint;

/** 指示器paint */

private Paint dotPaint;

/** 外圓環(huán)寬度 */

private int outerRingWidth;

/** 內(nèi)圓環(huán)寬度 */

private int innerRingWidth;

/** 表盤圓環(huán)總度數(shù) */

private final int totalAngle = 210;

/** 圓弧上總共刻度數(shù) */

private final int totalDegreeScale = 30;

/** 各分數(shù)刻度文本 */

private String[] scores = new String[] {"350", "較差", "550", "中等", "600", "良好", "650", "優(yōu)秀", "700", "極好", "950"};

/** 信用分數(shù) */

private int score = 715;

/** 當前掃過的數(shù)值角度 */

private float curProgressAngle;

/** 動畫時長 */

private final long ANIM_DURATION = 2000;

/** 指示器結束時的角度 */

private float stopAngle;

/** 信用評級文字 */

private String creditStr;

繪制外層兩個圓弧,以12點鐘為圓弧中點,左右各有105°

private void drawRing (Canvas canvas) {

ringPaint.setAlpha(80);

int startAngle = -90-totalAngle/2; //圓環(huán)起始角度,12點鐘位置為-90°

//繪制外圓環(huán)

ringPaint.setStrokeWidth(outerRingWidth);

RectF rectF = new RectF(outerRingWidth, outerRingWidth, getWidth()-outerRingWidth, getHeight()-outerRingWidth);

canvas.drawArc(rectF, startAngle, totalAngle, false, ringPaint);

//繪制內(nèi)圓環(huán)

ringPaint.setStrokeWidth(innerRingWidth);

int padding = outerRingWidth + dp2px(getContext(), 12);

RectF innerRectF = new RectF(padding, padding, getWidth()-padding, getHeight()-padding);

canvas.drawArc(innerRectF, startAngle, totalAngle, false, ringPaint);

}

圓弧上總共有30個小刻度,遍歷每隔小刻度,每個小刻度繪制較細的線,每3個刻度繪制一次文本,每6個刻度繪制一次較粗的線,通過旋轉(zhuǎn)畫布來實現(xiàn),以使在同一位置繪制刻度和文本得以實現(xiàn),最后要恢復畫布。

private void drawDegreeScale(Canvas canvas) {

canvas.save();

int padding = dp2px(getContext(), 10);

canvas.rotate(-totalAngle/2, getWidth()/2, getHeight()/2); //將畫布逆時間旋轉(zhuǎn)一半弧度,使以左端點為刻度起點

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

ringPaint.setAlpha(80);

ringPaint.setStrokeWidth(2);

//每一格繪制一個淺色刻度

canvas.drawLine(getWidth()/2, padding, getWidth()/2, padding+innerRingWidth, ringPaint);

ringPaint.setAlpha(100);

ringPaint.setStrokeWidth(3);

//每6格刻度繪制一個深色刻度,即大刻度

if (i%6==0) {

canvas.drawLine(getWidth()/2, padding, getWidth()/2, padding+innerRingWidth+5, ringPaint);

}

//每三格刻度繪制一個文字

if (i%3==0) {

scoreTextPaint.setAlpha(180);

float textWidth = scoreTextPaint.measureText(scores[i/3]); //測量該文本寬度,需向左移動半個文本寬度以對齊

canvas.drawText(scores[i/3], getWidth()/2-textWidth/2, padding+innerRingWidth+dp2px(getContext(), 12), scoreTextPaint);

}

canvas.rotate(totalAngle/totalDegreeScale, getWidth()/2, getHeight()/2); //每次畫完從中心開始旋轉(zhuǎn)畫布單位刻度的弧度

}

canvas.restore(); //恢復角度

}

繪制中心文本,包括beta,分數(shù),信用評級,評估時間,這個很簡單,就是需要獲取文本的寬高調(diào)節(jié)依次垂直居中。

private void drawCenterText(Canvas canvas) {

//繪制當前分數(shù)

scoreTextPaint.setAlpha(255);

scoreTextPaint.setTextSize(170);

String curScore = String.valueOf(score);

Rect scoreRect = new Rect();

scoreTextPaint.getTextBounds(curScore, 0, curScore.length(), scoreRect); //需左移文字寬度以居中

canvas.drawText(curScore, getWidth()/2-scoreRect.width()/2, getHeight()/2, scoreTextPaint);

//繪制BETA文字

scoreTextPaint.setAlpha(150);

scoreTextPaint.setTextSize(35);

Rect betaRect= new Rect();

String betaStr = "BETA";

scoreTextPaint.getTextBounds(betaStr, 0, betaStr.length(), betaRect); //beta需向坐上移動

canvas.drawText(betaStr, getWidth()/2-betaRect.width()/2, getHeight()/2-scoreRect.height()-betaRect.height()/2, scoreTextPaint);

//繪制信用等級文本

scoreTextPaint.setAlpha(200);

scoreTextPaint.setTextSize(75);

Rect creditRect = new Rect();

scoreTextPaint.getTextBounds(creditStr, 0, creditStr.length(), creditRect);

canvas.drawText(creditStr, getWidth()/2-creditRect.width()/2, getHeight()/2+scoreRect.height()/2+20, scoreTextPaint);

//繪制評估時間

scoreTextPaint.setAlpha(150);

scoreTextPaint.setTextSize(35);

float timeStrWidth = scoreTextPaint.measureText("評估時間:2020.07.27");

canvas.drawText("評估時間:2020.07.27", getWidth()/2-timeStrWidth/2, getHeight()/2+scoreRect.height()+10, scoreTextPaint);

}

繪制進度動畫小圓點:根據(jù)屬性curProgressAngle的值來繪制指示器小圓點,圓心為中心,小圓點軌跡為圓,由三角函數(shù)知識得到坐標軌跡方程。

同時,使用Paint的BlurMaskFilter實現(xiàn)小圓點高斯模糊發(fā)光效果,發(fā)光模式為Blur.SOLID,內(nèi)外發(fā)光。

private void drawDot(Canvas canvas) {

scoreTextPaint.setAlpha(230);

float x = (float) (getWidth()/2 + (getWidth()/2-outerRingWidth)*Math.sin(Math.toRadians(curProgressAngle)));

float y = (float) (getHeight()/2 - (getWidth()/2-outerRingWidth)*Math.cos(Math.toRadians(curProgressAngle)));

canvas.drawCircle(x, y, outerRingWidth, dotPaint);

}

使用ValueAnimator動畫實時更新curProgressAngle并重繪,以實現(xiàn)小圓點實時更新位置實現(xiàn)進度動畫。

private void startIndicatorAnim() {

ValueAnimator valueAnimator = ValueAnimator.ofFloat(-105, stopAngle);

valueAnimator.setDuration(ANIM_DURATION);

valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());

valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

curProgressAngle = (float) animation.getAnimatedValue();

postInvalidate(); //數(shù)值改變實時更新繪制

}

});

valueAnimator.start();

}

根據(jù)分數(shù)計算小圓點結束時的實際角度:在當前大刻度范圍的結束角度,為之前刻度角度加上在該區(qū)間按比例得出的角度,30個小刻度共210°,每個小刻度perLevelAngle角度為7°

private String showCreditLevel() {

int startAngle = -105;

int perLevelAngle = totalAngle/5; //有5段大刻度

String creditLevelStr = null;

if (score < 350) {

creditLevelStr = "信用較差";

stopAngle = startAngle;

} else if (score >= 350 && score < 550) {

creditLevelStr = "信用較差";

stopAngle = startAngle + (float)(score-350)/(550-350)*perLevelAngle;

} else if (score >= 550 && score < 600) {

creditLevelStr = "信用中等";

stopAngle = startAngle + perLevelAngle + (float)(score-550)/(600-550)*perLevelAngle;

} else if (score >= 600 && score < 650) {

creditLevelStr = "信用良好";

stopAngle = startAngle + perLevelAngle*2 + (float)(score-600)/(650-600)*perLevelAngle;

} else if (score >= 650 && score < 700) {

creditLevelStr = "信用優(yōu)秀";

stopAngle = startAngle + perLevelAngle*3 + (float)(score-650)/(700-650)*perLevelAngle;

} else if (score >= 700 && score < 950) {

creditLevelStr = "信用極好";

stopAngle = startAngle + perLevelAngle*4 + (float)(score-700)/(950-700)*perLevelAngle;

}

return creditLevelStr;

}

最后,通過ObjectAnimator實時更新分數(shù)。

public void runWithAnimation(int number){

ObjectAnimator objectAnimator = ObjectAnimator.ofInt(this, "score", 0, number);

objectAnimator.setDuration(ANIM_DURATION);

objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());

objectAnimator.start();

}

最后附上完整代碼,喜歡的給個??吧。

/**

* create by libo

* create on 2020/7/27

* description 支付寶芝麻信用自定義view

*/

public class SesameCreditView extends View {

/** 圓環(huán)paint */

private Paint ringPaint;

/** 信用分文字paint */

private Paint scoreTextPaint;

/** 指示器paint */

private Paint dotPaint;

/** 外圓環(huán)寬度 */

private int outerRingWidth;

/** 內(nèi)圓環(huán)寬度 */

private int innerRingWidth;

/** 表盤圓環(huán)總度數(shù) */

private final int totalAngle = 210;

/** 圓弧上總共刻度數(shù) */

private final int totalDegreeScale = 30;

/** 各分數(shù)刻度文本 */

private String[] scores = new String[] {"350", "較差", "550", "中等", "600", "良好", "650", "優(yōu)秀", "700", "極好", "950"};

/** 信用分數(shù) */

private int score = 715;

/** 當前掃過的數(shù)值角度 */

private float curProgressAngle;

/** 動畫時長 */

private final long ANIM_DURATION = 2000;

/** 指示器結束時的角度 */

private float stopAngle;

/** 信用評級文字 */

private String creditStr;

public SesameCreditView(Context context) {

super(context);

init();

}

public SesameCreditView(Context context, @Nullable AttributeSet attrs) {

super(context, attrs);

init();

}

private void init() {

outerRingWidth = dp2px(getContext(), 3);

innerRingWidth = dp2px(getContext(), 10);

ringPaint = new Paint();

ringPaint.setColor(getResources().getColor(R.color.white));

ringPaint.setAntiAlias(true);

ringPaint.setStyle(Paint.Style.STROKE);

scoreTextPaint = new Paint();

scoreTextPaint.setColor(getResources().getColor(R.color.white));

scoreTextPaint.setAntiAlias(true);

scoreTextPaint.setTextSize(32);

dotPaint = new Paint();

dotPaint.setColor(getResources().getColor(R.color.white));

dotPaint.setAntiAlias(true);

dotPaint.setMaskFilter(new BlurMaskFilter(outerRingWidth, BlurMaskFilter.Blur.SOLID)); //設置指示器發(fā)光

creditStr = showCreditLevel();

startIndicatorAnim();

runWithAnimation(score);

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

drawRing(canvas);

drawDegreeScale(canvas);

drawCenterText(canvas);

drawDot(canvas);

}

/**

* 繪制圓弧

* @param canvas

*/

private void drawRing (Canvas canvas) {

ringPaint.setAlpha(80);

int startAngle = -90-totalAngle/2; //圓環(huán)起始角度,12點鐘位置為-90°

//繪制外圓環(huán)

ringPaint.setStrokeWidth(outerRingWidth);

RectF rectF = new RectF(outerRingWidth, outerRingWidth, getWidth()-outerRingWidth, getHeight()-outerRingWidth);

canvas.drawArc(rectF, startAngle, totalAngle, false, ringPaint);

//繪制內(nèi)圓環(huán)

ringPaint.setStrokeWidth(innerRingWidth);

int padding = outerRingWidth + dp2px(getContext(), 12);

RectF innerRectF = new RectF(padding, padding, getWidth()-padding, getHeight()-padding);

canvas.drawArc(innerRectF, startAngle, totalAngle, false, ringPaint);

}

/**

* 繪制圓環(huán)刻度,分數(shù)文字

*/

private void drawDegreeScale(Canvas canvas) {

canvas.save();

int padding = dp2px(getContext(), 10);

canvas.rotate(-totalAngle/2, getWidth()/2, getHeight()/2); //將畫布逆時間旋轉(zhuǎn)一半弧度,使以左端點為刻度起點

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

ringPaint.setAlpha(80);

ringPaint.setStrokeWidth(2);

//每一格繪制一個淺色刻度

canvas.drawLine(getWidth()/2, padding, getWidth()/2, padding+innerRingWidth, ringPaint);

ringPaint.setAlpha(100);

ringPaint.setStrokeWidth(3);

//每6格刻度繪制一個深色刻度,即大刻度

if (i%6==0) {

canvas.drawLine(getWidth()/2, padding, getWidth()/2, padding+innerRingWidth+5, ringPaint);

}

//每三格刻度繪制一個文字

if (i%3==0) {

scoreTextPaint.setAlpha(180);

float textWidth = scoreTextPaint.measureText(scores[i/3]); //測量該文本寬度,需向左移動半個文本寬度以對齊

canvas.drawText(scores[i/3], getWidth()/2-textWidth/2, padding+innerRingWidth+dp2px(getContext(), 12), scoreTextPaint);

}

canvas.rotate(totalAngle/totalDegreeScale, getWidth()/2, getHeight()/2); //每次畫完從中心開始旋轉(zhuǎn)畫布單位刻度的弧度

}

canvas.restore(); //恢復角度

}

/**

* 繪制中心文本

*/

private void drawCenterText(Canvas canvas) {

//繪制當前分數(shù)

scoreTextPaint.setAlpha(255);

scoreTextPaint.setTextSize(170);

String curScore = String.valueOf(score);

Rect scoreRect = new Rect();

scoreTextPaint.getTextBounds(curScore, 0, curScore.length(), scoreRect); //需左移文字寬度以居中

canvas.drawText(curScore, getWidth()/2-scoreRect.width()/2, getHeight()/2, scoreTextPaint);

//繪制BETA文字

scoreTextPaint.setAlpha(150);

scoreTextPaint.setTextSize(35);

Rect betaRect= new Rect();

String betaStr = "BETA";

scoreTextPaint.getTextBounds(betaStr, 0, betaStr.length(), betaRect); //beta需向坐上移動

canvas.drawText(betaStr, getWidth()/2-betaRect.width()/2, getHeight()/2-scoreRect.height()-betaRect.height()/2, scoreTextPaint);

//繪制信用等級文本

scoreTextPaint.setAlpha(200);

scoreTextPaint.setTextSize(75);

Rect creditRect = new Rect();

scoreTextPaint.getTextBounds(creditStr, 0, creditStr.length(), creditRect);

canvas.drawText(creditStr, getWidth()/2-creditRect.width()/2, getHeight()/2+scoreRect.height()/2+20, scoreTextPaint);

//繪制評估時間

scoreTextPaint.setAlpha(150);

scoreTextPaint.setTextSize(35);

float timeStrWidth = scoreTextPaint.measureText("評估時間:2020.07.27");

canvas.drawText("評估時間:2020.07.27", getWidth()/2-timeStrWidth/2, getHeight()/2+scoreRect.height()+10, scoreTextPaint);

}

/**

* 繪制進度動畫小圓點

*/

private void drawDot(Canvas canvas) {

scoreTextPaint.setAlpha(230);

float x = (float) (getWidth()/2 + (getWidth()/2-outerRingWidth)*Math.sin(Math.toRadians(curProgressAngle)));

float y = (float) (getHeight()/2 - (getWidth()/2-outerRingWidth)*Math.cos(Math.toRadians(curProgressAngle)));

canvas.drawCircle(x, y, outerRingWidth, dotPaint);

}

/**

* 啟動指示器加載動畫

*/

private void startIndicatorAnim() {

ValueAnimator valueAnimator = ValueAnimator.ofFloat(-105, stopAngle);

valueAnimator.setDuration(ANIM_DURATION);

valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());

valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation) {

curProgressAngle = (float) animation.getAnimatedValue();

postInvalidate(); //數(shù)值改變實時更新繪制

}

});

valueAnimator.start();

}

/**

* 設置信用水平,每一刻小刻度是7°

* 在當前大刻度范圍的結束角度,為之前刻度角度加上在該區(qū)間按比例得出的角度

*/

private String showCreditLevel() {

int startAngle = -105;

int perLevelAngle = totalAngle/5; //有5段大刻度

String creditLevelStr = null;

if (score < 350) {

creditLevelStr = "信用較差";

stopAngle = startAngle;

} else if (score >= 350 && score < 550) {

creditLevelStr = "信用較差";

stopAngle = startAngle + (float)(score-350)/(550-350)*perLevelAngle;

} else if (score >= 550 && score < 600) {

creditLevelStr = "信用中等";

stopAngle = startAngle + perLevelAngle + (float)(score-550)/(600-550)*perLevelAngle;

} else if (score >= 600 && score < 650) {

creditLevelStr = "信用良好";

stopAngle = startAngle + perLevelAngle*2 + (float)(score-600)/(650-600)*perLevelAngle;

} else if (score >= 650 && score < 700) {

creditLevelStr = "信用優(yōu)秀";

stopAngle = startAngle + perLevelAngle*3 + (float)(score-650)/(700-650)*perLevelAngle;

} else if (score >= 700 && score < 950) {

creditLevelStr = "信用極好";

stopAngle = startAngle + perLevelAngle*4 + (float)(score-700)/(950-700)*perLevelAngle;

}

return creditLevelStr;

}

public void runWithAnimation(int number){

ObjectAnimator objectAnimator = ObjectAnimator.ofInt(this, "score", 0, number);

objectAnimator.setDuration(ANIM_DURATION);

objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());

objectAnimator.start();

}

public int getScore() {

return score;

}

public void setScore(int score) {

this.score = score;

}

private int dp2px(Context context, float dp) {

final float scale = context.getResources().getDisplayMetrics().density;

return (int) (dp * scale + 0.5f);

}

}

總結

以上是生活随笔為你收集整理的android自定义表盘部件,Android自定义view仿支付宝芝麻信用表盘的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。