美文网首页
View layout 简要过程

View layout 简要过程

作者: zhaoyubetter | 来源:发表于2016-11-27 16:12 被阅读23次

    Layout的作用是ViewGroup用来确定子元素的位置,当ViewGroup的位置被确定后,她会调用 onLayout来遍历其所有子元素并调用子元素的layout方法,子元素,又继续上面的过程;
    layout用来确定view本身的位置,onLayout方法确定所有子元素位置

    /**
     * 4个顶点位置,都是相对于其父
    **/
     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;
            }
    
            int oldL = mLeft;
            int oldT = mTop;
            int oldB = mBottom;
            int oldR = mRight;
    
            boolean changed = isLayoutModeOptical(mParent) ?
                    setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
    
            if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
                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;
        }
    

    根据布局模式(xml:layoutMode)来判断来调用 setOpticalFrame 还是 setFrame 来完成自身布局

    protected boolean setFrame(int left, int top, int right, int bottom) {
            boolean changed = false;
    
            if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
                changed = true;
    
                // Remember our drawn bit
                int drawn = mPrivateFlags & PFLAG_DRAWN;
    
                int oldWidth = mRight - mLeft;
                int oldHeight = mBottom - mTop;
                int newWidth = right - left;
                int newHeight = bottom - top;
                boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
    
                // Invalidate our old position
                invalidate(sizeChanged);
    
                mLeft = left;
                mTop = top;
                mRight = right;
                mBottom = bottom;
                mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
    
                mPrivateFlags |= PFLAG_HAS_BOUNDS;
    
    
                if (sizeChanged) {
                    sizeChange(newWidth, newHeight, oldWidth, oldHeight);
                }
    
                if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
                    // If we are visible, force the DRAWN bit to on so that
                    // this invalidate will go through (at least to our parent).
                    // This is because someone may have invalidated this view
                    // before this call to setFrame came in, thereby clearing
                    // the DRAWN bit.
                    mPrivateFlags |= PFLAG_DRAWN;
                    invalidate(sizeChanged);
                    // parent display list may need to be recreated based on a change in the bounds
                    // of any child
                    invalidateParentCaches();
                }
    
                // Reset drawn bit to original value (invalidate turns it off)
                mPrivateFlags |= drawn;
    
                mBackgroundSizeChanged = true;
                if (mForegroundInfo != null) {
                    mForegroundInfo.mBoundsChanged = true;
                }
    
                notifySubtreeAccessibilityStateChangedIfNeeded();
            }
            return changed;
        }
    

    onLayout 交给子类来实现,如:LinearLayout,TextView 等控件;

    getMeasureHeight 与 getHeight 方法对比
    这2个方法都是用来获取控件的高的,不同的时,getMeasureHeight形成与测量阶段,getHeight形成于layout阶段;

     public final int getMeasuredHeight() {
            return mMeasuredHeight & MEASURED_SIZE_MASK;
        }
    
     public final int getHeight() {
            return mBottom - mTop;
        }
    

    在Layout布局时,我们可能会这样写,这样就会造成,measureHeight 与 Height的结果,

     public void layout(int l, int t, int r, int b) {
        super.layout(100 + l, t, r, b);
    }
    

    相关文章

      网友评论

          本文标题:View layout 简要过程

          本文链接:https://www.haomeiwen.com/subject/fklnpttx.html