好久不寫博客,最近沒任務就來寫寫博客,今天就寫個簡單的自定義圓形進度條的實現,最終效果如下:
好了,我們首先分析一下如果是你做這種效果需要哪些步驟呢?考慮幾秒再看下面的。別偷懶。
你思考了麼?這麼快就來看步驟了,太懶了吧!
其實很簡單,3個步驟,1.畫中間綠色的圓形;2.畫外面藍色的進度(其實是一個扇形);3.畫進度(圖中的數字1%-99%、完成),畫的綠色圓形將藍色的扇形覆蓋住,就是上圖的效果了,然後慢慢改變藍色扇形的角度就行了。具體實現步驟如下圖:
是不是很簡單?當然簡單!
那麼開始寫具體實現代碼!
首先自定義一個類繼承自View,實現構造方法初始化:扇形,綠色圓形,字,這三個屬性所需的畫筆(我用了三個畫筆是爲了區分大家方便看,當然也可以只用一個畫筆就行了)
package com.custom.my.widget;
public class CircleProgressBar extends View {
private Context context;
private int height,width; //自定義控件的寬高
private float progress; //進度
private Paint paint; //藍色扇形所需的畫筆
private Paint bkPaint; //綠色圓形所需的畫筆
private Paint tvPaint; //圓裏面的進度字所需的畫筆
private Rect mBound; //用於獲取字體的大小
public CircleProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
this.paint = new Paint();
this.bkPaint = new Paint();
this.tvPaint = new Paint();
this.mBound = new Rect();
init();
}
private void init(){
paint.setStyle(Style.FILL);
paint.setColor(Color.parseColor("#50A3FE"));
paint.setAntiAlias(true);
bkPaint.setStyle(Style.FILL);
bkPaint.setColor(Color.parseColor("#00ff00"));
bkPaint.setAntiAlias(true);
tvPaint.setColor(Color.parseColor("#ffffff"));
tvPaint.setTextSize(15);
}
}
畫筆等屬性初始化完成後,我們需要獲取我們設置的寬高(這個圓形進度條的整體寬高),而我們獲取View寬高的地方是重寫View的onMeasure方法:
//獲取當前控件的高度和寬度,單位是像素
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
}
獲取到了寬高後我們就可以開始畫了,在CircleProgressBar 的onDraw方法裏面畫扇形,圓形,字。
private float set2Degree(float sendFt){ //將進度的數值變爲弧度數值,進度100,弧度有360,所以比例是3.6
return sendFt*3.6f;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(width*height==0){
return;
}
canvas.drawArc(new RectF(0, 0, width, height), 270, set2Degree(progress), true, paint); //畫藍色扇形
canvas.drawCircle(width / 2, height / 2, width / 2 - 5, bkPaint); //畫綠色圓形,半徑比藍色扇形的小5px
if(progress < 100){ //進度沒達到100%時顯示進度
String strPro = String.valueOf((int)progress)+"%";
tvPaint.getTextBounds(strPro,0,strPro.length(),mBound);
canvas.drawText(strPro,width/2 - mBound.width()/2,height/2 + mBound.height()/2,tvPaint);
}else{ //達到100%後顯示完成
String text = "完成";
tvPaint.getTextBounds(text,0,text.length(),mBound);
canvas.drawText(text,width/2 - mBound.width()/2,height/2 + mBound.height()/2,tvPaint);
}
}
當然畫了後我們要實時更新弧度,所以我們在CircleProgressBar 裏面加個public方法來實時更新進度。
public void setProgress(float progress){
this.progress = progress;
postInvalidate();
}
當進度發生改變後調用改方法修改進度即可。使用用例如下:
xml佈局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.custom.my.activity.CircleProgressAcitivity">
<com.custom.my.widget.CircleProgressBar
android:id="@+id/circle_progress"
android:layout_centerInParent="true"
android:layout_width="65dp"
android:layout_height="65dp" />
</RelativeLayout>
Activity中如下,爲了模擬進度,我們使用handler來不停地更新進度:
public class CircleProgressAcitivity extends AppCompatActivity {
private CircleProgressBar circleProgressBar;
private float progress = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_circle_progress);
circleProgressBar = (CircleProgressBar) findViewById(R.id.circle_progress);
handler.sendEmptyMessageDelayed(1,100);
}
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what == 1){
if(progress <= 99){
++progress;
circleProgressBar.setProgress(progress); //更新進度條
this.sendEmptyMessageDelayed(1, 100);
}
}
}
};
}
完成了,整個思路很簡單,代碼也很簡單,當然如果想自定義字體的顏色,字體大小等,可以結合之前我寫的那個自定義條形進度條的那篇博客http://blog.csdn.net/gsw333/article/details/50803313就行,當然如果覺得太醜也可以把中間的綠色換成一個beautiful圖片就行了,反正做法都是一樣。
最後最後最後!!!!!!!!!!如果你覺得不錯幫我頂一頂!!!!!!!!!如果覺得不好,請給我的辛苦碼字頂一頂!!!!!!!!!