1. 思路分析
自定義View步驟:
1>:values__attrs.xml跺株,自定義屬性跷睦;
2>:在第三個(gè)構(gòu)造方法中缚够,獲取自定義屬性娶聘;
3>:onMeasure:不是非必須的,測(cè)量控件大谐饴恕将鸵;
4>:onDraw:所有繪制代碼都寫在onDraw方法中;
思路分析
1>:自定義屬性:內(nèi)圓顏色佑颇、外圓顏色顶掉、圓弧寬度、中間文字顏色挑胸、文字大醒魍病;
2>:自定義ProgressBar茬贵,繼承View簿透;
2. 效果圖如下
3. 代碼如下
1>:attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- 炫酷進(jìn)度條 -->
<declare-styleable name="ProgressBar">
<!-- 內(nèi)圓弧背景 -->
<attr name="innerBackground" format="color"/>
<!-- 外圓弧背景 -->
<attr name="outterBackground" format="color"/>
<!-- 圓弧寬度 -->
<attr name="roundWidth" format="dimension"/>
<!-- 文字大小 -->
<attr name="progressTextSize" format="dimension"/>
<!-- 文字顏色 -->
<attr name="progressTextColor" format="color"/>
</declare-styleable>
</resources>
2>:ProgressBar
/**
* ================================================
* Email: 2185134304@qq.com
* Created by Novate 2018/12/29 15:25
* Version 1.0
* Params:
* Description: 圓形進(jìn)度條
* ================================================
*/
public class ProgressBar extends View {
// 內(nèi)圓弧默認(rèn)顏色
private int mInnerBackground = Color.RED ;
// 外圓弧默認(rèn)顏色
private int mOuterBackground = Color.RED;
// 圓弧寬度
private int mRoundWidth = 10 ;
// 文字大小
private float mProgressTextSize = 15 ;
// 文字顏色
private int mProgressTextColor = Color.RED;
// 3個(gè)畫筆 內(nèi)圓弧畫筆、外圓弧畫筆解藻、文字畫筆
private Paint mInnerPaint,mOuterPaint,mTextPaint;
// 設(shè)置最大進(jìn)度
private int mMax = 100 ;
// 當(dāng)前進(jìn)度
private int mProgress = 0 ;
// 百分比
private float persent ;
public ProgressBar(Context context) {
this(context,null);
}
public ProgressBar(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public ProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// 獲取自定義屬性
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ProgressBar);
// 內(nèi)圓弧背景
mInnerBackground = typedArray.getColor(R.styleable.ProgressBar_innerBackground,mInnerBackground);
// 外圓弧背景
mOuterBackground = typedArray.getColor(R.styleable.ProgressBar_outterBackground,mOuterBackground);
// 圓弧寬度
mRoundWidth = typedArray.getDimensionPixelSize(R.styleable.ProgressBar_roundWidth,(int)dip2px(mRoundWidth));
// 文字大小
mProgressTextSize = typedArray.getDimensionPixelSize(R.styleable.ProgressBar_progressTextSize,sp2px(mProgressTextSize));
// 文字顏色
mProgressTextColor = typedArray.getColor(R.styleable.ProgressBar_progressTextColor,mProgressTextColor);
// 釋放資源
typedArray.recycle();
// 初始化3個(gè)畫筆
initPaint();
}
private void initPaint() {
// 內(nèi)圓弧畫筆
mInnerPaint = new Paint();
// 設(shè)置抗鋸齒
mInnerPaint.setAntiAlias(true);
// 內(nèi)圓弧顏色
mInnerPaint.setColor(mInnerBackground);
// 圓弧寬度
mInnerPaint.setStrokeWidth(mRoundWidth);
// 只繪制圖形邊緣(描邊) Paint.Style.FILL 只繪制圖形內(nèi)容 Paint.Style.FILL_AND_STROKE 既繪制輪廓也繪制內(nèi)容
mInnerPaint.setStyle(Paint.Style.STROKE);
//外圓弧畫筆
mOuterPaint = new Paint() ;
mOuterPaint.setAntiAlias(true);
mOuterPaint.setColor(mOuterBackground);
mOuterPaint.setStrokeWidth(mRoundWidth); //設(shè)置圓弧寬度
mOuterPaint.setStyle(Paint.Style.STROKE);
//文字畫筆
mTextPaint = new Paint() ;
mTextPaint.setAntiAlias(true);
mTextPaint.setTextSize(mProgressTextSize);
mTextPaint.setColor(mProgressTextColor);
}
/**
* 測(cè)量控件大小
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 與qq計(jì)步器一樣老充,只寫最簡(jiǎn)單的形式,直接獲取寬高螟左,也就是說對(duì)應(yīng)到xml布局文件中的寬高屬性只能設(shè)置固定值啡浊,
// 不能是wrap_content,如果想要設(shè)置wrap_content胶背,這里首先要獲取寬高模式巷嚣,然后根據(jù)寬高模式再去獲取寬高
int width = MeasureSpec.getSize(widthMeasureSpec) ;
int height = MeasureSpec.getSize(heightMeasureSpec) ;
// 測(cè)量大小 這里保證是正方形:下邊2種方式
// setMeasuredDimension(width>height?height:width,width>height?height:width);
setMeasuredDimension(Math.min(width, height), Math.min(width, height));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 1. 畫內(nèi)圓[是圓形,不是圓弧]
drawCircle(canvas) ;
// 2. 畫外圓弧
drawArc(canvas) ;
// 3. 畫文字
drawText(canvas) ;
}
/**
* 畫文字
*/
private void drawText(Canvas canvas) {
// 要畫的文字
String text = (int)(persent*100)+"%";
Rect rect = new Rect();
// 文字區(qū)域
mTextPaint.getTextBounds(text,0,text.length(),rect);
int dx = getWidth()/2 - rect.width()/2;
Paint.FontMetricsInt fontMetricsInt = mTextPaint.getFontMetricsInt();
int dy = (fontMetricsInt.bottom-fontMetricsInt.top)/2-fontMetricsInt.bottom;
// 基線
int baseLine = getHeight()/2+dy;
canvas.drawText(text,dx,baseLine,mTextPaint);
}
/**
* 設(shè)置最大進(jìn)度
*/
public synchronized void setMax(int max){
this.mMax=max;
}
/**
* 當(dāng)前進(jìn)度
*/
public synchronized void setProgress(int progress){
if (progress < 0){
}
this.mProgress=progress;
// 不斷的獲取到當(dāng)前進(jìn)度钳吟,然后需要不斷的刷新
invalidate();
}
/**
* 2. 畫外圓弧廷粒, 固定寫法
*/
private void drawArc(Canvas canvas) {
RectF rectF = new RectF(0+mRoundWidth/2,0+mRoundWidth/2,getWidth()-mRoundWidth/2,getHeight()-mRoundWidth/2);
if (mProgress == 0)
return;
persent = (float)mProgress/mMax;
// param1: 圓弧形狀和大小范圍 param2: 開始的角度 param3: 掃過的角度 params4: 設(shè)置在畫圓弧的時(shí)候,是否經(jīng)過圓形 param5: 畫筆
canvas.drawArc(rectF,0,persent*360,false,mOuterPaint);
}
/**
* 1. 畫內(nèi)圓:是圓形砸抛,不是圓弧, 固定寫法
*/
private void drawCircle(Canvas canvas) {
// 中心點(diǎn)
int center = getWidth()/2;
// param1:圓心x坐標(biāo) param2:圓心y坐標(biāo) param3:圓的半徑 param4: 畫筆
canvas.drawCircle(center,center,center-mRoundWidth/2,mInnerPaint);
}
private int sp2px(float sp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
}
private float dip2px(int dip) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, getResources().getDisplayMetrics());
}
}
3>:activity_progressbar
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<com.novate.test.customview.ProgressBar
android:layout_width="match_parent"
android:layout_height="match_parent"
app:innerBackground="@color/colorPrimary"
app:outterBackground="@color/colorAccent"
app:roundWidth="20dp"
app:progressTextColor="@color/colorAccent"
app:progressTextSize="20sp"
android:id="@+id/progress_bar"
/>
</LinearLayout>
4>:ProgressBarActivity
public class ProgressBarActivity extends AppCompatActivity {
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_progressbar);
final ProgressBar mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
// 設(shè)置最大進(jìn)度
mProgressBar.setMax(4000);
// 屬性動(dòng)畫
ValueAnimator valueAnimator = ObjectAnimator.ofFloat(0,4000);
valueAnimator.setDuration(2000);
valueAnimator.start();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
// 不斷的獲取當(dāng)前進(jìn)度
float currrentProgress = (float) animation.getAnimatedValue();
// 設(shè)置當(dāng)前進(jìn)度
mProgressBar.setProgress((int) currrentProgress);
}
});
}
}