自定義View概述
1.自定義View分類
- 自定義View 直接繼承View主要是繪制
- 自定義ViewGroup 繼承ViewGroup主要是計算所有子控件的大小和位置
- 繼承相應的View,如TextView,Button,LinearLayout等
2.自定義View的流程

自定義view的繪制流程
3.相應的構造函數(shù):
當你繼承View會有4個相應的構造方法:
public void SloopView(Context context) {}
public void SloopView(Context context, AttributeSet attrs) {}
public void SloopView(Context context, AttributeSet attrs, int defStyleAttr) {}
public void SloopView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {}
- 第一個是new對象的時候調用的方法
- 第二個是在布局文件中使用的時候調用的方法
- 第三個是設置主題的時候調用的方法,這里你可以指定,也可以寫死
- 第四個是在21版本新添加的方法,暫且不論
4.View的測量(onMeasure)
這個方法的作用是用來測量View的相應的方法,基本上有固定的模板代碼,其實就是計算整個View占用的大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int realWidth;/*真是的寬度*/
int realHeight;/*真是的高度*/
if (widthMode == MeasureSpec.EXACTLY) {
realWidth = width;
} else if (widthMode == MeasureSpec.AT_MOST) {
realWidth = 500;/*這里是定義的最大值*/
} else {
realWidth = 500;/*未知寬度的時候*/
}
if (heightMode == MeasureSpec.EXACTLY) {
realHeight = height;
} else if (heightMode == MeasureSpec.AT_MOST) {
realHeight = 500;/*這里是定義的最大值*/
} else {
realHeight = 500;/*未知高度的時候*/
}
setMeasuredDimension(realWidth, realHeight);
}
這里記住相應的三種狀態(tài):
- AT_MOST 最大值,但是不會超過父容器
- EXACTLY 具體指,指定了具體的大小
- UNSPECIFIED 未知大小,這里是父容器沒有指定相應的大小(其實上面的兩種狀態(tài)考慮到的話就可以不用去設置這個了)
上面這個例子基本上就是onMeasure的模板代碼,但是有的控件涉及到重繪界面,那么只要把相應的realWidth和realHeight寫成動態(tài)的就可以了.但是基本的邏輯是不會改變的...
5.View的繪制(onDraw)
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
這個方法主要涉及到Canvas的相應操作,后面會單提出來去講.其實就是相應的API的一些繪制操作.
6.View大小的改變操作(onSizeChanged)
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
其實這個方法是確定View大小的方法,但是如果你調用** requestLayout();**方法的時候是強制重繪,整個繪制流程都會重新走一遍,也就是說onMeasue(),onSizeChanged()和onDraw()都會重新執(zhí)行,這樣也就達到了相應的改變View的效果了,這種一般都是和手勢有關的View.
7.子View位置的確定(onLayout)
確定布局的函數(shù)是onLayout,它用于確定子View的位置,在自定義ViewGroup中會用到,他調用的是子View的layout函數(shù)。

View位置的確定
其實這里面只有一張圖的事情,理解了這張圖就能更好的設置相應的位置了.
8.相應的屬性值
其實這部分的代碼也是相應的模板代碼,只要記住了就行.
- 在相應的res文件夾下創(chuàng)建一個attrs的xml文件,用來實現(xiàn)自定義View的style(也就是可以使用的屬性)
<declare-styleable name="HorizontalEditItemView"> <attr name="title" format="string" /> <attr name="etHint" format="string" /> </declare-styleable>
這里的屬性你可以隨意定義,只要符合你的習慣就行
- 在自定義View中使用該屬性
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HorizontalEditItemView); String title = typedArray.getString(R.styleable.HorizontalEditItemView_title); String etHint = typedArray.getString(R.styleable.HorizontalEditItemView_etHint); typedArray.recycle();
這里使用完TypedArray之后一定要進行釋放.
概述的內容就這么多,其實寫的挺晦澀的,這里講的太仔細的話,效果還是一樣的,只有你真正的去使用,才能去理解.這里只是一個概述,后面的文章會在使用的時候更加完善的講解!