019.View的layout过程

 View的Layout过程,也就是布局子元素的过程,ViewGroup通过这个过程来确定子元素的位置,当ViewGroup的位置被确定了以后,就会在onLayout中遍历所有的子元素并且调用这些元素的layout方法,在layout方法中onLayout方法会被回调.下面我们从View的Layout方法开始看:
    
public void layout(int l, int t, int r, int b) {
        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
        }
    //首先,在layout的时候,我们已经拿到了View的位置了,然后,我们记录下之前的View的位置信息。
        int oldL = mLeft;
        int oldT = mTop;
        int oldB = mBottom;
        int oldR = mRight;
        //isLayoutModeOptical返回为true需要mParent为ViewGroup派生类的对象,
        //并且mParent的isLayoutModeOptical也需要是true,一般来说,只要layoutMode不是LAYOUT_MODE_OPTICAL_BOUNDS
        //那么,什么叫LAYOUT_MODE_OPTICAL_BOUNDS ?一般我们绘制了View的阴影、发光区域什么的,这种情况下,我们会有个区域影响到别的控件
       //下面主要讲setFrame ,setFrame的最终结果就是重新设置View的位置,并且返回是否改变了View的位置。
         boolean changed = isLayoutModeOptical(mParent) ?
                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);

        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
        //执行onLayout的方法,当然,也是遍历子View,每个都要告诉ViewGroup   
            onLayout(changed, l, t, r, b);
            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;

            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnLayoutChangeListeners != null) {
                ArrayList<OnLayoutChangeListener> listenersCopy =
                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
                int numListeners = listenersCopy.size();
                for (int i = 0; i < numListeners; ++i) {
                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
                }
            }
        }

        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
    }

猜你喜欢

转载自blog.csdn.net/savelove911/article/details/52317006