自定義ViewGroup
Constructor->onFinishInflate->onMeasure..->onSizeChanged->onLayout->addOnGlobalLayoutListener->onWindowFocusChanged->onMeasure->onLayout
由上可知,onMeasure和onLayout會被多次調(diào)用.
- Constructor:構(gòu)造方法,View初始化的時候調(diào)用,在這里是無法獲取其子控件的引用的.更加無法獲取寬高了
- onFinishInflate:當布局初始化完畢后回調(diào),在這里可以獲取所有直接子View的引用,但是無法獲取寬高.
- onMeasure:當測量控件寬高時回調(diào),當調(diào)用了requestLayout()也會回調(diào)onMeasure.在這里一定可以通過getMeasuredHeight()和getMeasuredWidth()來獲取控件的高和寬,但不一定可以通過getHeight()和getWidth()來獲取控件寬高,因為getHeight()和getWidth()必須要等onLayout方法回調(diào)之后才能確定.
- onSizeChanged:當控件的寬高發(fā)生變化時回調(diào),和onMeasure一樣,一定可以通過getMeasuredHeight()和getMeasuredWidth()來獲取控件的高和寬,因為它是在onMeasure方法執(zhí)行之后和onLayout方法之前回調(diào)的.
- onLayout:當確定控件的位置時回調(diào),當調(diào)用了requestLayout()也會回調(diào)onLayout.在這里一定可以通過getHeight()和getWidth()獲取控件的寬高,同時由于onMeasure方法比onLayout方法先執(zhí)行,所以在這里也可以通過getMeasuredHeight()和getMeasuredWidth()來獲取控件的高和寬.
- addOnGlobalLayoutListener:當View的位置確定完后會回調(diào)改監(jiān)聽方法,它是緊接著onLayout方法執(zhí)行而執(zhí)行的,只要onLayout方法調(diào)用了,那么addOnGlobalLayoutListener的監(jiān)聽器就會監(jiān)聽到.在這里getMeasuredHeight()和getMeasuredWidth()和getHeight()和getWidth()都可以獲取到寬高.
- onWindowFocusChanged:當View的焦點發(fā)送改變時回調(diào),在這里getMeasuredHeight()和getMeasuredWidth()和getHeight()和getWidth()都可以獲取到寬高.Activity也可以通過重寫該方法來判斷當前的焦點是否發(fā)送改變了;需要注意的是這里View獲取焦點和失去焦點都會回調(diào).
measure()之后,也就是在onMeasure()中調(diào)用getMeasureWidth()可以獲取View的測量寬高
layout()之后,也就是在onLayout(),方法中可以調(diào)用getWidth()獲取View的寬高
兩者都有值之后,是相等的,只是被賦值的時間不同
測量孩子的寬高
onMeasure中
int childCount = getChildCount();
for (int i=0;i<childCount;i++){
View child = getChildAt(i);
//只有調(diào)用如下方法才可計算子視圖的寬高
measureChild(child,widthMeasureSpec,heightMeasureSpec);
LinearLayout.LayoutParams layoutParams =(LinearLayout.LayoutParams) child.getLayoutParams();
Log.e("maigin",layoutParams.leftMargin+"");
Log.e("msg",child.getMeasuredHeight()+"---"+child.getMeasuredWidth());
}
獲得child被添加到ViewGroup里時LayoutParams必須復寫下面的方法
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
//children被添加到ViewGroup時的layoutParams
return new MarginLayoutParams(getContext(),attrs);
}
放置child在onLayout方法中
childView.layout(laft,top,right,bottom); parent的左上角為原點,X軸向右為正,Y軸向下為正左上角的坐標,右下角的坐標