自定义ViewGroup
Constructor->onFinishInflate->onMeasure..->onSizeChanged->onLayout->addOnGlobalLayoutListener->onWindowFocusChanged->onMeasure->onLayout
由上可知,onMeasure和onLayout会被多次调用.
- Constructor:构造方法,View初始化的时候调用,在这里是无法获取其子控件的引用的.更加无法获取宽高了
- onFinishInflate:当布局初始化完毕后回调,在这里可以获取所有直接子View的引用,但是无法获取宽高.
- onMeasure:当测量控件宽高时回调,当调用了requestLayout()也会回调onMeasure.在这里一定可以通过getMeasuredHeight()和getMeasuredWidth()来获取控件的高和宽,但不一定可以通过getHeight()和getWidth()来获取控件宽高,因为getHeight()和getWidth()必须要等onLayout方法回调之后才能确定.
- onSizeChanged:当控件的宽高发生变化时回调,和onMeasure一样,一定可以通过getMeasuredHeight()和getMeasuredWidth()来获取控件的高和宽,因为它是在onMeasure方法执行之后和onLayout方法之前回调的.
- onLayout:当确定控件的位置时回调,当调用了requestLayout()也会回调onLayout.在这里一定可以通过getHeight()和getWidth()获取控件的宽高,同时由于onMeasure方法比onLayout方法先执行,所以在这里也可以通过getMeasuredHeight()和getMeasuredWidth()来获取控件的高和宽.
- addOnGlobalLayoutListener:当View的位置确定完后会回调改监听方法,它是紧接着onLayout方法执行而执行的,只要onLayout方法调用了,那么addOnGlobalLayoutListener的监听器就会监听到.在这里getMeasuredHeight()和getMeasuredWidth()和getHeight()和getWidth()都可以获取到宽高.
- onWindowFocusChanged:当View的焦点发送改变时回调,在这里getMeasuredHeight()和getMeasuredWidth()和getHeight()和getWidth()都可以获取到宽高.Activity也可以通过重写该方法来判断当前的焦点是否发送改变了;需要注意的是这里View获取焦点和失去焦点都会回调.
measure()之后,也就是在onMeasure()中调用getMeasureWidth()可以获取View的测量宽高
layout()之后,也就是在onLayout(),方法中可以调用getWidth()获取View的宽高
两者都有值之后,是相等的,只是被赋值的时间不同
测量孩子的宽高
onMeasure中
int childCount = getChildCount();
for (int i=0;i<childCount;i++){
View child = getChildAt(i);
//只有调用如下方法才可计算子视图的宽高
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轴向下为正左上角的坐标,右下角的坐标