Android繪圖:自定義View之——矩形進度條、圓環進度條、填充型進度條、時鐘
阿新 • • 發佈:2019-01-03
主函式
這幾種進度條的主函式都是類似的,所以下面我只給出了一個填充型進度條的主函式,其他幾個主函式只是在這基礎上改動一下按鈕id(即與各自佈局裡面的id相同即可),還有改動一下相對應的類即可。
public class MainActivity extends AppCompatActivity {
private Button mButtonStart;
private MyProgress myProgress;
private int progress;
private static final int PROGRESS=0X23;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case PROGRESS:
progress++;
if (progress<=100){
myProgress.setCurrentProgress(progress);
handler.sendEmptyMessageDelayed(PROGRESS,200 );
}
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButtonStart= (Button) findViewById(R.id.button_start);
myProgress= (MyProgress) findViewById(R.id.myprogress);
mButtonStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.sendEmptyMessageDelayed(PROGRESS,1000);
}
});
}
}
矩形進度條自定義View
public class Rectangle extends View {
private int mProgress;
private Paint mCurrentProgress;
private Paint mMaxProgress;
private Paint mPaintText;
private int mWidth;
private int mHeight;
public Rectangle(Context context) {
super(context);
}
public Rectangle(Context context, AttributeSet attrs) {
super(context, attrs);
mCurrentProgress = new Paint();
mCurrentProgress.setColor(Color.YELLOW);
mCurrentProgress.setAntiAlias(true);
mMaxProgress = new Paint();
mMaxProgress.setColor(Color.WHITE);
mMaxProgress.setAntiAlias(true);
mPaintText = new Paint();
mPaintText.setColor(Color.RED);
mPaintText.setStrokeWidth(5);
mPaintText.setAntiAlias(true);
mPaintText.setTextSize(100);
mPaintText.setTextAlign(Paint.Align.CENTER);
}
public int getmProgress() {
return mProgress;
}
public void setmProgress(int mProgress) {
this.mProgress = mProgress;
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth=getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
mHeight= getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(mWidth / 2-160, mHeight / 2-250,mWidth / 2+160, mHeight / 2+250, mMaxProgress);
canvas.drawRect(mWidth / 2-160, mHeight / 2+250-(mProgress/100f*500),mWidth / 2+160, mHeight / 2+250, mCurrentProgress);
canvas.drawText(mProgress+"%", mWidth / 2, mHeight / 2, mPaintText);
}
}
矩形進度條的佈局
<Button
android:id="@+id/button_round"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="開始下載"/>
<com.example.administrator.definedviewdemo.Wiget.Rectangle
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/rectangle"/>
成像圖
圓環形進度條自定義View
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by Administrator on 2015/9/16.
*/
public class RoundProgressBar extends View {
private Paint mPaintBackCircle;
private Paint mPaintInfrontCircle;
private int currentProgress;
private int mwidth;
private int mheight;
private Paint mPaintText;
private RectF mOval;
public int getCurrentProgress() {
return currentProgress;
}
public void setCurrentProgress(int currentProgress) {
this.currentProgress = currentProgress;
invalidate();//告訴UI執行緒重新繪製
}
public RoundProgressBar(Context context) {
super(context);
}
public RoundProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintBackCircle=new Paint();
mPaintBackCircle.setColor(Color.GRAY);
mPaintBackCircle.setStrokeWidth(1);
mPaintBackCircle.setAntiAlias(true);
mPaintBackCircle.setStyle(Paint.Style.STROKE);
mPaintInfrontCircle=new Paint();
mPaintInfrontCircle.setColor(Color.GREEN);
//這裡的寬度是畫填充圓環時的寬度,即兩個圓的半徑之差。
mPaintInfrontCircle.setStrokeWidth(40);
mPaintInfrontCircle.setAntiAlias(true);
mPaintInfrontCircle.setStyle(Paint.Style.STROKE);
mPaintText=new Paint();
mPaintText.setColor(Color.RED);
mPaintText.setTextSize(50);
mPaintText.setTextAlign(Paint.Align.CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mwidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
mheight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(mwidth/2, mheight/2,200,mPaintBackCircle);
canvas.drawCircle(mwidth/2, mheight/2,160,mPaintBackCircle);
// 設定個新的長方形,掃描測量,減去的值為兩個半徑的中間值
RectF oval1=new RectF(mwidth / 2-180, mheight / 2-180,mwidth / 2+180, mheight / 2+180);
// 畫弧,第一個引數是RectF:該類是第二個引數是角度的開始,第三個引數是多少度,第四個引數是真的時候畫扇形,是假的時候畫弧線
canvas.drawArc( oval1, 0,currentProgress/100f*360 ,false, mPaintInfrontCircle);
canvas.drawText(currentProgress+"%",mwidth/2,mheight/2,mPaintText);
}
}
圓環形進度條的佈局
<Button
android:id="@+id/button_round"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="開始下載"/>
<com.example.administrator.definedviewdemo.Wiget.RoundProgressBar
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/round"/>
成像圖
填充型進度條自定義View
public class MyProgress extends View {
private int mWidth;
private int mHeight;
private Paint mPaintBackGround;
private Paint mPaintCurrent;
private Paint mPaintText;
private int currentProgress;
public int getCurrentProgress() {
return currentProgress;
}
public void setCurrentProgress(int currentProgress) {
this.currentProgress = currentProgress;
invalidate();//告訴UI執行緒重新繪製
}
public MyProgress(Context context) {
super(context);
}
public MyProgress(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintBackGround = new Paint();
mPaintBackGround.setAntiAlias(true);
mPaintBackGround.setColor(Color.GRAY);
mPaintCurrent = new Paint();
mPaintCurrent.setAntiAlias(true);
mPaintCurrent.setColor(Color.GREEN);
mPaintText = new Paint();
mPaintText.setAntiAlias(true);
mPaintText.setColor(Color.BLACK);
mPaintText.setTextSize(100);
mPaintText.setTextAlign(Paint.Align.CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(mWidth / 2, mHeight / 2, 200, mPaintBackGround);
canvas.drawCircle(mWidth / 2, mHeight / 2, 200/100f*currentProgress,mPaintCurrent);
canvas.drawText(currentProgress+"%", mWidth / 2, mHeight / 2, mPaintText);
}
}
填充型進度條佈局
<Button
android:id="@+id/button_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="開始下載"/>
<com.example.administrator.definedviewdemo.Wiget.MyProgress
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/myprogress"/>
成像圖
時鐘自定義View
public class MyView extends View {
private int mWidth;
private int mHeight;
private Paint mPaint;
private Paint mPaintMinute;
private Paint mPaintHour;
private Paint mPaintCircle;
private Paint mPaintText;
private Calendar mCalendar;
private static final int NEED_UPDATE=34;
private Handler mHandler=new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case NEED_UPDATE:
mCalendar=Calendar.getInstance();
invalidate();
mHandler.sendEmptyMessageDelayed(NEED_UPDATE, 1000);
break;
default:
break;
}
};
};
public MyView(Context context) {
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
mCalendar=Calendar.getInstance();
//檢視api以瞭解它的具體使用方法(canvas View的api)
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(5);
mPaint.setAntiAlias(true);
mPaintHour = new Paint();
mPaintHour.setColor(Color.BLACK);
mPaintHour.setStrokeWidth(5);
mPaintHour.setAntiAlias(true);
mPaintMinute = new Paint();
mPaintMinute.setColor(Color.GREEN);
mPaintMinute.setStrokeWidth(5);
mPaintMinute.setAntiAlias(true);
mPaintCircle = new Paint();
mPaintCircle.setColor(Color.BLUE);
mPaintCircle.setStrokeWidth(5);
mPaintCircle.setAntiAlias(true);
mPaintCircle.setStyle(Paint.Style.STROKE);
mPaintText = new Paint();
mPaintText.setColor(Color.DKGRAY);
mPaintText.setTextSize(30);
mPaintText.setTextAlign(Paint.Align.CENTER);
mPaintText.setStrokeWidth(5);
mPaintText.setAntiAlias(true);
mHandler.sendEmptyMessageDelayed(NEED_UPDATE, 1000);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
@Override
protected void onDraw(Canvas canvas) {
{
super.onDraw(canvas);
// 傳入畫素值,檢視api
//畫出錶盤
canvas.drawCircle(mWidth / 2, mHeight / 2, 300, mPaintCircle);
canvas.drawCircle(mWidth / 2, mHeight / 2, 10, mPaintCircle);
for (int i = 1; i <= 12; i++) {
//儲存畫布此時的狀態
canvas.save();
canvas.rotate(360 / 12 * i, mWidth / 2, mHeight / 2);
canvas.drawLine(mWidth / 2, mHeight / 2 - 300, mWidth / 2 - 1, mHeight / 2 - 280, mPaint);
canvas.drawText("" + i, mWidth / 2, mHeight / 2 - 240, mPaintText);
//配合save()使用
canvas.restore();
}
//畫出時鐘的分針
int minute=mCalendar.get(Calendar.MINUTE);
int hour=mCalendar.get(Calendar.HOUR);
float degreeMinute=minute/60f*360;
canvas.save();
canvas.rotate(degreeMinute,mWidth / 2, mHeight / 2);
canvas.drawLine(mWidth / 2, mHeight / 2-200, mWidth / 2, mHeight / 2+18, mPaintMinute);
canvas.restore();
//畫出時鐘的時針,計算時針的位置,因為時針一天走兩圈,所以除以720,在乘以角度360
float degreeHour=(hour*60+minute)/12f/60*360;
canvas.save();
canvas.rotate(degreeHour,mWidth / 2, mHeight / 2);
canvas.drawLine(mWidth / 2, mHeight / 2-150, mWidth / 2, mHeight / 2+14, mPaintHour);
canvas.restore();
}
//畫出秒針
int seconde=mCalendar.get(Calendar.SECOND);
float degreeSeconde=seconde*6;
canvas.save();
canvas.rotate(degreeSeconde,mWidth / 2, mHeight / 2);
canvas.drawLine(mWidth / 2, mHeight / 2-250, mWidth / 2, mHeight / 2+24, mPaint);
canvas.restore();
}
}
特別注意:
//畫線的時候,起始點的高度和終止點的高度千萬不能寫錯了——即起始點的高度小於終止點的高度,而且起始點離內圓圓心的長度大於終止點到內圓的長度。
canvas.drawLine(mwidth / 2, mheight / 2 -100, mwidth / 2, mheight / 2 +25, mPaintLine);
時鐘自定義View佈局
<com.example.administrator.definedviewdemo.Wiget.MyView
android:layout_width="match_parent"
android:layout_height="match_parent" />