前面簡單的講述了Android中自定義控件的理論和流程圖,今天經過代碼來詳細的講解一下其中的方法html
首先先建立一個類 CircularView 繼承於 View,以後實現構造方法(初始化步驟)java
public class CircularView extends View { public CircularView(Context context) { super(context); } public CircularView(Context context, AttributeSet attrs) { super(context, attrs); } public CircularView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public CircularView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } }
View的構造函數有四種重載,View構造函數的參數有多有少,android
有四個參數的構造函數在API21的時候才添加上,暫不考慮。canvas
有三個參數的構造函數中第三個參數是默認的Style,這裏的默認的Style是指它在當前Application或Activity所用的Theme中的默認Style,且只有在明確調用的時候纔會生效ide
//調用了三個參數的構造函數,明確指定第三個參數 this(context, attrs, com.android.internal.R.attr.imageButtonStyle);
因爲三個參數的構造函數第三個參數通常不經常使用,因此也暫不考慮函數
//通常在直接New一個View的時候調用。 public void CircularView(Context context) {} //通常在layout文件中使用的時候會調用,關於它的全部屬性(包括自定義屬性)都會包含在attrs中傳遞進來。 public void CircularView(Context context, AttributeSet attrs) {}
使用方式:(佈局文件中)佈局
<com.zhangqie.customcontrol.demo1.CircularView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="@color/colorAccent" />
onMeasure方法 (測量View大小)this
View的大小不只由自身所決定,同時也會受到父控件的影響,爲了咱們的控件能更好的適應各類狀況,通常會本身進行測量。code
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthsize MeasureSpec.getSize(widthMeasureSpec); //取出寬度的確切數值 int widthmode MeasureSpec.getMode(widthMeasureSpec); //取出寬度的測量模式 int heightsize MeasureSpec.getSize(heightMeasureSpec); //取出高度的確切數值 int heightmode MeasureSpec.getMode(heightMeasureSpec); //取出高度的測量模式 }
從上面能夠看出 onMeasure 函數中有 widthMeasureSpec 和 heightMeasureSpec 這兩個 int 類型的參數, 毫無疑問他們是和寬高相關的, 但它們其實不是寬和高, 而是由寬、高和各自方向上對應的測量模式來合成的一個值:htm
測量模式一共有三種, 被定義在 Android 中的 View 類的一個內部類View.MeasureSpec中:
模式 | 二進制數值 | 描述 |
---|---|---|
UNSPECIFIED | 00 | 默認值,父控件沒有給子view任何限制,子View能夠設置爲任意大小。 |
EXACTLY | 01 | 表示父控件已經確切的指定了子View的大小。 |
AT_MOST | 10 | 表示子View具體大小沒有尺寸限制,可是存在上限,上限通常爲父View大小。 |
onSizeChanged方法 肯定View的大小,這個函數在視圖大小發生改變時調用
/*** * 肯定View的大小(這個函數在視圖大小發生改變時調用。) * * 寬度,高度,上一次寬度,上一次高度。 * 只需關注 寬度(w), 高度(h) 便可,這兩個參數就是View最終的大小。 * @param w * @param h * @param oldw * @param oldh */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); Log.i(TAG,"onSizeChanged"); }
onLayout 方法 肯定子View佈局位置
/**** * 佈局-Layout過程用於設置視圖在屏幕中顯示的位置,onLayout通常只會在自定義ViewGroup中才會使用 * * @param changed * @param left * @param top * @param right * @param bottom */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); Log.i(TAG,"onLayout"); }
肯定佈局的函數是onLayout,它用於肯定子View的位置,在自定義ViewGroup中會用到,他調用的是子View的layout函數。
在自定義ViewGroup中,onLayout通常是循環取出子View,而後通過計算得出各個子View位置的座標值,而後用如下函數設置子View位置。
onDraw 方法,繪製內容
/*** * 繪製-draw過程主要用於利用前兩步獲得的參數,將視圖顯示在屏幕上,到這裏也就完成了整個的視圖繪製工做 * @param canvas */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); }
onDraw是實際繪製的部分,也就是咱們真正關心的部分,使用的是Canvas繪圖。