自定義View就是繼承一個View的子孫類或View類,然後重寫其中的一些方法來完成界面的美觀效果。
效果:
佈局:
<so.wih.android.myview.MyLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
代碼:
public class MyLayout extends View {
private int mWidth;
private int mHeight;
private Paint mCirclePaint;
private int circleRadius ;
private Paint mPaintLine;
private Paint mPaintText;
private Calendar mCalendar;
public static final int what_update = 100;
public Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case what_update :
mCalendar=Calendar.getInstance();//這一句必須有,如果沒有就不刷新時間
invalidate();//重繪界面 會調用onDraw方法
handler.sendEmptyMessageDelayed(what_update,1000);
break;
}
}
};
public MyLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyLayout(Context context) {
super(context);
init();
}
/**
* 初始化控件
*/
private void init() {
//圓半徑
circleRadius = 300 ;
//畫圓的畫筆
mCirclePaint = new Paint();
mCirclePaint.setColor(Color.GREEN);
mCirclePaint.setStrokeWidth(10);//設置繪製的筆畫寬度
mCirclePaint.setStyle(Paint.Style.STROKE); //空心
//畫刻度的畫筆
mPaintLine = new Paint();
mPaintLine.setColor(Color.RED);
mPaintLine.setStrokeWidth(10);
//畫數字的畫筆
mPaintText = new Paint();
mPaintText.setColor(Color.GRAY);
mPaintText.setTextSize(35);
mPaintText.setStrokeWidth(10);
mPaintText.setTextAlign(Paint.Align.CENTER); //文字居中
//發送消息
handler.sendEmptyMessage(what_update);
//獲取時間
mCalendar = Calendar.getInstance();
}
/*
* 當一個view 從創建對象,到顯示在屏幕中,的幾個重要步驟:
*
* 1- 測量控件大小
* onMeasure
* 2- 指定控件位置
* onLayout
* 3- 繪製控件的內容
* onDraw
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 我們要做的就是設置測量大小,即,view想要的大小
mWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
mHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(mWidth, mHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 繪製大圓
canvas.drawCircle(mWidth/2, mHeight/2, circleRadius, mCirclePaint);
//小圓
canvas.drawCircle(mWidth / 2, mHeight / 2, 5, mCirclePaint);
//繪製刻度
for (int i = 1; i <=12 ; i++) {
//大刻度
canvas.save(); //保存當前矩陣並將其存儲到私有堆棧上
float degrees = 360/12*i ;
canvas.rotate(degrees,mWidth/2, mHeight/2);
canvas.drawLine(mWidth / 2 ,(mHeight / 2-circleRadius) ,
mWidth / 2 ,(mHeight / 2-circleRadius+20) ,mPaintLine);
canvas.drawText(""+i,mWidth/2,(mHeight / 2-circleRadius+50),mPaintText);
/**
* 這個調用是爲了平衡save(),用於移除自上次保存時的矩陣/剪輯狀態的所有修改。
* 不能比svae()調用的次數多
*/
canvas.restore();
//小刻度
canvas.save(); //保存當前矩陣並將其存儲到私有堆棧上
float degrees2 = 360/12*(i-1)+15 ;
canvas.rotate(degrees2,mWidth/2, mHeight/2);
canvas.drawLine(mWidth / 2 ,(mHeight / 2-circleRadius) ,
mWidth / 2 ,(mHeight / 2-circleRadius+10) ,mPaintLine);
// canvas.drawText(""+i,mWidth/2,(mHeight / 2-circleRadius+50),mPaintText);
/**
* 這個調用是爲了平衡save(),用於移除自上次保存時的矩陣/剪輯狀態的所有修改。
* 不能比svae()調用的次數多
*/
canvas.restore();
}
//繪製時針、分針和秒針
int hour = mCalendar.get(Calendar.HOUR);
int minute = mCalendar.get(Calendar.MINUTE);
int second = mCalendar.get(Calendar.SECOND);
//小時的角度
float hourDegree = 360 / 12f * hour ;
canvas.save();//這個方法和restore配合用於錶盤歸位
canvas.rotate(hourDegree, mWidth / 2, mHeight / 2);//以錶盤中心爲中心旋轉現在分鐘數*(360度/60分)
canvas.drawLine(mWidth / 2 ,mHeight / 2 , mWidth / 2 ,(mHeight / 2 - circleRadius+200) ,mPaintLine);
canvas.restore();//錶盤歸於原位
//分鐘的角度
float minuteDegree = 360 / 60f * minute ;
canvas.save();//這個方法和restore配合用於錶盤歸位
canvas.rotate(minuteDegree, mWidth / 2, mHeight / 2);//以錶盤中心爲中心旋轉現在分鐘數*(360度/60分)
canvas.drawLine(mWidth / 2 ,mHeight / 2 , mWidth / 2 ,(mHeight / 2 - circleRadius+150) ,mPaintLine);
canvas.restore();//錶盤歸於原位
//秒針的角度
float sedondDegree = 360 /60f * second ;
canvas.save();//這個方法和restore配合用於錶盤歸位
canvas.rotate(sedondDegree, mWidth / 2, mHeight / 2);//以錶盤中心爲中心旋轉現在分鐘數*(360度/60分)
canvas.drawLine(mWidth / 2 ,mHeight / 2 , mWidth / 2 ,(mHeight / 2 - circleRadius+100) ,mPaintLine);
canvas.restore();//錶盤歸於原位
}
}
參考自:http://blog.csdn.net/litao660044/article/details/48500417
這個大神寫的自定義控件很詳細。