Android自定義View
Android自定義View時(shí),一般會(huì)涉及到onMeasure峡钓、onLayout钓瞭、onSizeChanged、onDraw以及和事件分發(fā)傳遞相關(guān)的方法等
Android自定義View之onMeasure
一般Android在繪制View時(shí)會(huì)調(diào)用onMeasure方法來計(jì)算其寬高,當(dāng)控件的layout_width和layout_height設(shè)為match_parent或者wrap_content顯示的大小由其父容器控件來決定。若設(shè)置為固定大小的值删顶,那么就顯示其設(shè)定的值
MeasureSpec.getSize()會(huì)解析MeasureSpec得到測量值的大小
MeasureSpec.getMode()會(huì)得到3個(gè)int類型的值:
1)MeasureSpec.EXACTLY
父容器決定控件的大小竖螃,忽略其本身的大小淑廊,當(dāng)width或height設(shè)為match_parent或者固定大小時(shí),模式為EXACTLY,控件去占據(jù)父容器的剩余空間
2)MeasureSpec.AT_MOST
控件最大可以達(dá)到的指定大小特咆,當(dāng)width或height設(shè)置為wrap_content季惩,模式為AT_MOST
3)MeasureSpec.UNSPECIFIED
父容器不對(duì)控件施加任何約束,控件可以是任意大小腻格,一般父容器是AdapterView
setMeasuredDimension方法用于設(shè)置實(shí)際控件的大小
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = measureSize(px2dp(DEFAULT_WIDTH),widthMeasureSpec);
int height = measureSize(px2dp(DEFAULT_HEIGHT),heightMeasureSpec);
setMeasuredDimension(width,height);
}
private int measureSize(int defaultSize,int spec){
int specMode = MeasureSpec.getMode(spec);
int specSize = MeasureSpec.getSize(spec);
if (specMode == MeasureSpec.EXACTLY){
return specSize;
}else if (specMode == MeasureSpec.AT_MOST){
return Math.min(defaultSize,specSize);
}
return defaultSize;
}
Android自定義View之事件攔截分發(fā)機(jī)制
//分派事件
public boolean dispatchTouchEvent(MotionEvent ev)
//攔截事件
public boolean onInterceptTouchEvent(MotionEvent ev)
//處理事件
public boolean onTouchEvent(MotionEvent event)
其中View只包含dispatchTouchEvent和onTouchEvent兩個(gè)方法(另外Activity也只包含這兩個(gè)方法)
而ViewGroup具有全部3個(gè)方法
在ViewGroup中的dispatchTouchEvent方法里會(huì)調(diào)用其onInterceptTouchEvent方法
如果onInterceptTouchEvent方法返回true(即攔截事件)画拾,則會(huì)傳遞到其自己的onTouchEvent方法處理,到此就結(jié)束了
那么當(dāng)onInterceptTouchEvent方法返回false菜职,則會(huì)傳遞到其子控件的dispatchTouchEvent方法處理
如果這個(gè)子控件是繼承ViewGroup,則繼續(xù)按照這樣的方法執(zhí)行下去青抛,直到它是最后一個(gè)ViewGroup或者View
如果傳遞到的子控件是個(gè)View呢,它也會(huì)先執(zhí)行dispatchTouchEvent方法酬核,然后在其方法中調(diào)用到onTouchEvent方法
如果onTouchEvent方法返回true,則代表處理成功蜜另,然后一層一層的返回去
如果onTouchEvent方法返回false,則代表處理失敗,其會(huì)回到其父控件去執(zhí)行其父控件的onTouchEvent方法,直到onTouchEvent方法返回true
如果所有的onTouchEvent都返回false,那么這個(gè)touch事件則會(huì)丟失未處理
簡單來說執(zhí)行onInterceptTouchEvent方法返回true,執(zhí)行自己的onTouchEvent方法
否則就執(zhí)行其子控件的onInterceptTouchEvent方法(ViewGroup)或者onTouchEvent方法(View)
項(xiàng)目地址
https://github.com/peace710/Widget