从源码角度看一个view和ViewGroup的测量过程

来源:互联网 发布:python 相关系数 编辑:程序博客网 时间:2024/05/14 21:06

我们想想,如果我们要绘图,需要那几个参数?第一个:大小我们得知道吧,其次是位置,最后得知道怎么画吧 用什么颜色画,这和我们android中的绘图机制一模一样,接下来我们看看一个view的绘制
上节说performTraversals()会调用到performMeasure(),performLayout(),performDraw(),,我们先来看看第一步performMeasure()的源码
ViewRootImpl.java

 private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) { //用来追踪measure过程 tarce 是android的一个native方法,底层是一个python脚本,用来分析性能之类的,这里不再赘述,        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");        try {        //使用父控件masure子控件            mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);        } finally {        //marure完成后结束追踪            Trace.traceEnd(Trace.TRACE_TAG_VIEW);        }    }

在代码里讲的很清楚到底干了什么 我们来看measure方法源码,

 public final void measure(int widthMeasureSpec, int heightMeasureSpec) {        boolean optical = isLayoutModeOptical(this);        if (optical != isLayoutModeOptical(mParent)) {            Insets insets = getOpticalInsets();            int oWidth  = insets.left + insets.right;            int oHeight = insets.top  + insets.bottom;            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);        }        // Suppress sign extension for the low bytes        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);        if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||                widthMeasureSpec != mOldWidthMeasureSpec ||                heightMeasureSpec != mOldHeightMeasureSpec) {            // first clears the measured dimension flag            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;            resolveRtlPropertiesIfNeeded();            int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :                    mMeasureCache.indexOfKey(key);            if (cacheIndex < 0 || sIgnoreMeasureCache) {                // measure ourselves, this should set the measured dimension flag back                //这里调用的方法用来通知测量                onMeasure(widthMeasureSpec, heightMeasureSpec);                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;            } else {                long value = mMeasureCache.valueAt(cacheIndex);                // Casting a long to int drops the high 32 bits, no mask needed                setMeasuredDimensionRaw((int) (value >> 32), (int) value);                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;            }            // flag not set, setMeasuredDimension() was not invoked, we raise            // an exception to warn the developer            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {                throw new IllegalStateException("View with id " + getId() + ": "                        + getClass().getName() + "#onMeasure() did not set the"                        + " measured dimension by calling"                        + " setMeasuredDimension()");            }            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;        }        mOldWidthMeasureSpec = widthMeasureSpec;        mOldHeightMeasureSpec = heightMeasureSpec;        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension    }

上面的代码牵扯到很多数学运算,笔者不是很能看懂,但是笔者会努力去看懂的
我们来看看omMeasure方法
View.java

 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));    }

看起来已经要接近答案了 我们赶紧来看看这个getDefaultSize到底干了些什么

 public static int getDefaultSize(int size, int measureSpec) {        int result = size;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        switch (specMode) {        //这个属性不知道怎么说,它的名称翻译过来就是不确定的,未指定的,它的测量模式是这个view想多大就多大            case MeasureSpec.UNSPECIFIED:            result = size;            break;            //最大值模式 就是子控件设置了wrap_content,你会发现它把父控件占满了,hhhh,是不是由来已久的谜底被揭开了的感觉        case MeasureSpec.AT_MOST:        //精确模式,就是你设置多大就多大,来个250dp压压惊        case MeasureSpec.EXACTLY:            result = specSize;            break;        }        return result;    }

那么这个函数的作用就很明显了,就是根据你设置的模式来计算返回的宽高大小
这个宽高计算的只是这个View的,如果我们设置内边距什么的呢,和明显这个不是最终的,返回去看上面setMeasuredDimension()方法( view.java)

 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {        boolean optical = isLayoutModeOptical(this);        if (optical != isLayoutModeOptical(mParent)) {            Insets insets = getOpticalInsets();            int opticalWidth  = insets.left + insets.right;            int opticalHeight = insets.top  + insets.bottom;            measuredWidth  += optical ? opticalWidth  : -opticalWidth;            measuredHeight += optical ? opticalHeight : -opticalHeight;        }        setMeasuredDimensionRaw(measuredWidth, measuredHeight);    }

就完成了测量 ,那么怎么实现的对view树的测量呢 如果他是一个viewGroup则不会调用这个,ViewGroup的定义很清楚
public abstract class ViewGroup extends View implements ViewParent, ViewManager
并没有实现这个方法,我们很自然看他的子类,比如

public class RelativeLayout extends ViewGroup { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        if (mDirtyHierarchy) {            mDirtyHierarchy = false;            sortChildren();        }        int myWidth = -1;        int myHeight = -1;        int width = 0;        int height = 0;        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);        // Record our dimensions if they are known;        if (widthMode != MeasureSpec.UNSPECIFIED) {            myWidth = widthSize;        }        if (heightMode != MeasureSpec.UNSPECIFIED) {            myHeight = heightSize;        }        if (widthMode == MeasureSpec.EXACTLY) {            width = myWidth;        }        if (heightMode == MeasureSpec.EXACTLY) {            height = myHeight;        }        View ignore = null;        int gravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;        final boolean horizontalGravity = gravity != Gravity.START && gravity != 0;        gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;        final boolean verticalGravity = gravity != Gravity.TOP && gravity != 0;        int left = Integer.MAX_VALUE;        int top = Integer.MAX_VALUE;        int right = Integer.MIN_VALUE;        int bottom = Integer.MIN_VALUE;        boolean offsetHorizontalAxis = false;        boolean offsetVerticalAxis = false;        if ((horizontalGravity || verticalGravity) && mIgnoreGravity != View.NO_ID) {            ignore = findViewById(mIgnoreGravity);        }        final boolean isWrapContentWidth = widthMode != MeasureSpec.EXACTLY;        final boolean isWrapContentHeight = heightMode != MeasureSpec.EXACTLY;        // We need to know our size for doing the correct computation of children positioning in RTL        // mode but there is no practical way to get it instead of running the code below.        // So, instead of running the code twice, we just set the width to a "default display width"        // before the computation and then, as a last pass, we will update their real position with        // an offset equals to "DEFAULT_WIDTH - width".        final int layoutDirection = getLayoutDirection();        if (isLayoutRtl() && myWidth == -1) {            myWidth = DEFAULT_WIDTH;        }        View[] views = mSortedHorizontalChildren;        int count = views.length;        for (int i = 0; i < count; i++) {            View child = views[i];            //子View不为GONE 加载params进行测量            if (child.getVisibility() != GONE) {                LayoutParams params = (LayoutParams) child.getLayoutParams();                int[] rules = params.getRules(layoutDirection);                applyHorizontalSizeRules(params, myWidth, rules);                measureChildHorizontal(child, params, myWidth, myHeight);                if (positionChildHorizontal(child, params, myWidth, isWrapContentWidth)) {                    offsetHorizontalAxis = true;                }            }        }        views = mSortedVerticalChildren;        count = views.length;        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;        for (int i = 0; i < count; i++) {            final View child = views[i];            if (child.getVisibility() != GONE) {                final LayoutParams params = (LayoutParams) child.getLayoutParams();                applyVerticalSizeRules(params, myHeight, child.getBaseline());                measureChild(child, params, myWidth, myHeight);                if (positionChildVertical(child, params, myHeight, isWrapContentHeight)) {                    offsetVerticalAxis = true;                }                if (isWrapContentWidth) {                    if (isLayoutRtl()) {                        if (targetSdkVersion < Build.VERSION_CODES.KITKAT) {                            width = Math.max(width, myWidth - params.mLeft);                        } else {                            width = Math.max(width, myWidth - params.mLeft - params.leftMargin);                        }                    } else {                        if (targetSdkVersion < Build.VERSION_CODES.KITKAT) {                            width = Math.max(width, params.mRight);                        } else {                            width = Math.max(width, params.mRight + params.rightMargin);                        }                    }                }                if (isWrapContentHeight) {                    if (targetSdkVersion < Build.VERSION_CODES.KITKAT) {                        height = Math.max(height, params.mBottom);                    } else {                        height = Math.max(height, params.mBottom + params.bottomMargin);                    }                }                if (child != ignore || verticalGravity) {                    left = Math.min(left, params.mLeft - params.leftMargin);                    top = Math.min(top, params.mTop - params.topMargin);                }                if (child != ignore || horizontalGravity) {                    right = Math.max(right, params.mRight + params.rightMargin);                    bottom = Math.max(bottom, params.mBottom + params.bottomMargin);                }            }        }        // Use the top-start-most laid out view as the baseline. RTL offsets are        // applied later, so we can use the left-most edge as the starting edge.        View baselineView = null;        LayoutParams baselineParams = null;        for (int i = 0; i < count; i++) {            final View child = views[i];            if (child.getVisibility() != GONE) {                final LayoutParams childParams = (LayoutParams) child.getLayoutParams();                if (baselineView == null || baselineParams == null                        || compareLayoutPosition(childParams, baselineParams) < 0) {                    baselineView = child;                    baselineParams = childParams;                }            }        }        mBaselineView = baselineView;        if (isWrapContentWidth) {            // Width already has left padding in it since it was calculated by looking at            // the right of each child view            width += mPaddingRight;            if (mLayoutParams != null && mLayoutParams.width >= 0) {                width = Math.max(width, mLayoutParams.width);            }            width = Math.max(width, getSuggestedMinimumWidth());            width = resolveSize(width, widthMeasureSpec);            if (offsetHorizontalAxis) {                for (int i = 0; i < count; i++) {                    final View child = views[i];                    if (child.getVisibility() != GONE) {                        final LayoutParams params = (LayoutParams) child.getLayoutParams();                        final int[] rules = params.getRules(layoutDirection);                        if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) {                            centerHorizontal(child, params, width);                        } else if (rules[ALIGN_PARENT_RIGHT] != 0) {                            final int childWidth = child.getMeasuredWidth();                            params.mLeft = width - mPaddingRight - childWidth;                            params.mRight = params.mLeft + childWidth;                        }                    }                }            }        }        if (isWrapContentHeight) {            // Height already has top padding in it since it was calculated by looking at            // the bottom of each child view            height += mPaddingBottom;            if (mLayoutParams != null && mLayoutParams.height >= 0) {                height = Math.max(height, mLayoutParams.height);            }            height = Math.max(height, getSuggestedMinimumHeight());            height = resolveSize(height, heightMeasureSpec);            if (offsetVerticalAxis) {                for (int i = 0; i < count; i++) {                    final View child = views[i];                    if (child.getVisibility() != GONE) {                        final LayoutParams params = (LayoutParams) child.getLayoutParams();                        final int[] rules = params.getRules(layoutDirection);                        if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) {                            centerVertical(child, params, height);                        } else if (rules[ALIGN_PARENT_BOTTOM] != 0) {                            final int childHeight = child.getMeasuredHeight();                            params.mTop = height - mPaddingBottom - childHeight;                            params.mBottom = params.mTop + childHeight;                        }                    }                }            }        }        if (horizontalGravity || verticalGravity) {            final Rect selfBounds = mSelfBounds;            selfBounds.set(mPaddingLeft, mPaddingTop, width - mPaddingRight,                    height - mPaddingBottom);            final Rect contentBounds = mContentBounds;            Gravity.apply(mGravity, right - left, bottom - top, selfBounds, contentBounds,                    layoutDirection);            final int horizontalOffset = contentBounds.left - left;            final int verticalOffset = contentBounds.top - top;            if (horizontalOffset != 0 || verticalOffset != 0) {                for (int i = 0; i < count; i++) {                    final View child = views[i];                    if (child.getVisibility() != GONE && child != ignore) {                        final LayoutParams params = (LayoutParams) child.getLayoutParams();                        if (horizontalGravity) {                            params.mLeft += horizontalOffset;                            params.mRight += horizontalOffset;                        }                        if (verticalGravity) {                            params.mTop += verticalOffset;                            params.mBottom += verticalOffset;                        }                    }                }            }        }        if (isLayoutRtl()) {            final int offsetWidth = myWidth - width;            for (int i = 0; i < count; i++) {                final View child = views[i];                if (child.getVisibility() != GONE) {                    final LayoutParams params = (LayoutParams) child.getLayoutParams();                    params.mLeft -= offsetWidth;                    params.mRight -= offsetWidth;                }            }        }        setMeasuredDimension(width, height);    }}

看这个代码 是不是就理解了呢 这个就是很平常的加减 然后加入居中之类的
我们来看看linearLayout

 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        if (mDirtyHierarchy) {            mDirtyHierarchy = false;            sortChildren();        }        int myWidth = -1;        int myHeight = -1;        int width = 0;        int height = 0;        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);        final int heightSize = MeasureSpec.getSize(heightMeasureSpec);        // Record our dimensions if they are known;        if (widthMode != MeasureSpec.UNSPECIFIED) {            myWidth = widthSize;        }        if (heightMode != MeasureSpec.UNSPECIFIED) {            myHeight = heightSize;        }        if (widthMode == MeasureSpec.EXACTLY) {            width = myWidth;        }        if (heightMode == MeasureSpec.EXACTLY) {            height = myHeight;        }        View ignore = null;        int gravity = mGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK;        final boolean horizontalGravity = gravity != Gravity.START && gravity != 0;        gravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;        final boolean verticalGravity = gravity != Gravity.TOP && gravity != 0;        int left = Integer.MAX_VALUE;        int top = Integer.MAX_VALUE;        int right = Integer.MIN_VALUE;        int bottom = Integer.MIN_VALUE;        boolean offsetHorizontalAxis = false;        boolean offsetVerticalAxis = false;        if ((horizontalGravity || verticalGravity) && mIgnoreGravity != View.NO_ID) {            ignore = findViewById(mIgnoreGravity);        }        final boolean isWrapContentWidth = widthMode != MeasureSpec.EXACTLY;        final boolean isWrapContentHeight = heightMode != MeasureSpec.EXACTLY;        // We need to know our size for doing the correct computation of children positioning in RTL        // mode but there is no practical way to get it instead of running the code below.        // So, instead of running the code twice, we just set the width to a "default display width"        // before the computation and then, as a last pass, we will update their real position with        // an offset equals to "DEFAULT_WIDTH - width".        final int layoutDirection = getLayoutDirection();        if (isLayoutRtl() && myWidth == -1) {            myWidth = DEFAULT_WIDTH;        }        View[] views = mSortedHorizontalChildren;        int count = views.length;        for (int i = 0; i < count; i++) {            View child = views[i];            if (child.getVisibility() != GONE) {                LayoutParams params = (LayoutParams) child.getLayoutParams();                int[] rules = params.getRules(layoutDirection);                applyHorizontalSizeRules(params, myWidth, rules);                measureChildHorizontal(child, params, myWidth, myHeight);                if (positionChildHorizontal(child, params, myWidth, isWrapContentWidth)) {                    offsetHorizontalAxis = true;                }            }        }        views = mSortedVerticalChildren;        count = views.length;        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;        for (int i = 0; i < count; i++) {            final View child = views[i];            if (child.getVisibility() != GONE) {                final LayoutParams params = (LayoutParams) child.getLayoutParams();                applyVerticalSizeRules(params, myHeight, child.getBaseline());                measureChild(child, params, myWidth, myHeight);                if (positionChildVertical(child, params, myHeight, isWrapContentHeight)) {                    offsetVerticalAxis = true;                }                if (isWrapContentWidth) {                    if (isLayoutRtl()) {                        if (targetSdkVersion < Build.VERSION_CODES.KITKAT) {                            width = Math.max(width, myWidth - params.mLeft);                        } else {                            width = Math.max(width, myWidth - params.mLeft - params.leftMargin);                        }                    } else {                        if (targetSdkVersion < Build.VERSION_CODES.KITKAT) {                            width = Math.max(width, params.mRight);                        } else {                            width = Math.max(width, params.mRight + params.rightMargin);                        }                    }                }                if (isWrapContentHeight) {                    if (targetSdkVersion < Build.VERSION_CODES.KITKAT) {                        height = Math.max(height, params.mBottom);                    } else {                        height = Math.max(height, params.mBottom + params.bottomMargin);                    }                }                if (child != ignore || verticalGravity) {                    left = Math.min(left, params.mLeft - params.leftMargin);                    top = Math.min(top, params.mTop - params.topMargin);                }                if (child != ignore || horizontalGravity) {                    right = Math.max(right, params.mRight + params.rightMargin);                    bottom = Math.max(bottom, params.mBottom + params.bottomMargin);                }            }        }        // Use the top-start-most laid out view as the baseline. RTL offsets are        // applied later, so we can use the left-most edge as the starting edge.        View baselineView = null;        LayoutParams baselineParams = null;        for (int i = 0; i < count; i++) {            final View child = views[i];            if (child.getVisibility() != GONE) {                final LayoutParams childParams = (LayoutParams) child.getLayoutParams();                if (baselineView == null || baselineParams == null                        || compareLayoutPosition(childParams, baselineParams) < 0) {                    baselineView = child;                    baselineParams = childParams;                }            }        }        mBaselineView = baselineView;        if (isWrapContentWidth) {            // Width already has left padding in it since it was calculated by looking at            // the right of each child view            width += mPaddingRight;            if (mLayoutParams != null && mLayoutParams.width >= 0) {                width = Math.max(width, mLayoutParams.width);            }            width = Math.max(width, getSuggestedMinimumWidth());            width = resolveSize(width, widthMeasureSpec);            if (offsetHorizontalAxis) {                for (int i = 0; i < count; i++) {                    final View child = views[i];                    if (child.getVisibility() != GONE) {                        final LayoutParams params = (LayoutParams) child.getLayoutParams();                        final int[] rules = params.getRules(layoutDirection);                        if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_HORIZONTAL] != 0) {                            centerHorizontal(child, params, width);                        } else if (rules[ALIGN_PARENT_RIGHT] != 0) {                            final int childWidth = child.getMeasuredWidth();                            params.mLeft = width - mPaddingRight - childWidth;                            params.mRight = params.mLeft + childWidth;                        }                    }                }            }        }        if (isWrapContentHeight) {            // Height already has top padding in it since it was calculated by looking at            // the bottom of each child view            height += mPaddingBottom;            if (mLayoutParams != null && mLayoutParams.height >= 0) {                height = Math.max(height, mLayoutParams.height);            }            height = Math.max(height, getSuggestedMinimumHeight());            height = resolveSize(height, heightMeasureSpec);            if (offsetVerticalAxis) {                for (int i = 0; i < count; i++) {                    final View child = views[i];                    if (child.getVisibility() != GONE) {                        final LayoutParams params = (LayoutParams) child.getLayoutParams();                        final int[] rules = params.getRules(layoutDirection);                        if (rules[CENTER_IN_PARENT] != 0 || rules[CENTER_VERTICAL] != 0) {                            centerVertical(child, params, height);                        } else if (rules[ALIGN_PARENT_BOTTOM] != 0) {                            final int childHeight = child.getMeasuredHeight();                            params.mTop = height - mPaddingBottom - childHeight;                            params.mBottom = params.mTop + childHeight;                        }                    }                }            }        }        if (horizontalGravity || verticalGravity) {            final Rect selfBounds = mSelfBounds;            selfBounds.set(mPaddingLeft, mPaddingTop, width - mPaddingRight,                    height - mPaddingBottom);            final Rect contentBounds = mContentBounds;            Gravity.apply(mGravity, right - left, bottom - top, selfBounds, contentBounds,                    layoutDirection);            final int horizontalOffset = contentBounds.left - left;            final int verticalOffset = contentBounds.top - top;            if (horizontalOffset != 0 || verticalOffset != 0) {                for (int i = 0; i < count; i++) {                    final View child = views[i];                    if (child.getVisibility() != GONE && child != ignore) {                        final LayoutParams params = (LayoutParams) child.getLayoutParams();                        if (horizontalGravity) {                            params.mLeft += horizontalOffset;                            params.mRight += horizontalOffset;                        }                        if (verticalGravity) {                            params.mTop += verticalOffset;                            params.mBottom += verticalOffset;                        }                    }                }            }        }        if (isLayoutRtl()) {            final int offsetWidth = myWidth - width;            for (int i = 0; i < count; i++) {                final View child = views[i];                if (child.getVisibility() != GONE) {                    final LayoutParams params = (LayoutParams) child.getLayoutParams();                    params.mLeft -= offsetWidth;                    params.mRight -= offsetWidth;                }            }        }        setMeasuredDimension(width, height);    }

那么我们看看他到底干了些什么

1:判断子view是不是gone 是的话直接跳过
2 获取子view的LayoutParams,在xml中定义的参数,通过layout_weight定义的值累加到变量totalWeight中,然后判断如果view的height设置为零,但weight设置的大于0,则将height的值设置为LayoutParams.WRAP_CONTENT。
3然后调用measureChildWithMargins方法,该方法处理的逻辑:计算子view的measureSpec,即specMode和specSize,调用方法为:getChildMeasureSpec,调用两次,分别 计算宽和高,getChildMeasureSpec内部根据父view的measure和子view的layout_width和layout_height属性计算子view的measure。getChildMeasureSpec计算子view的measure,总结如下:1.如果在xml中指定了子view的具体大小,那么计算结果不管父的measure是什么,结果都是EXACITY+child_size,2.如果子view的height指定的值为FILL_PARENT,则返回的结果为:EXACITY+size,原因很简单:因为FILL_PARENT的意思是充满这个父view,所以返回的子view的measure就是view的大小。3.如果子view的大小为wrap_content,那么返回的结果都为AT_MOST+size,原因是:最大不能超过父view的大小。
4子view的measure确定好以后,然后调用子view的measure方法,如果子view是View对象,则该view的大小测量结束,开始下一个子view的循环,如果子view是ViewGroup那么,又开始一个新的递归,处理逻辑和上面一样,直到所有的view对象测量结束。
5所有的子view测量结束后,才开始对layout_weight计算,这样我们可能想到,如果父view已经被占满了,那么有可能layout_weight大于0的view对象是不会显示的,而计算layout_weight的方法也很简单,就是用总高度减去上面分析完mTotalLength的值,就是剩下,然后去平分给view对象,注意计算权重时优先去android:android:weightSum(LinearLayout的xml属性)的值,如果不设置该值会计算和,所以该值既然设置了,就一定要子view的weight的总和相等,否则平分可能不能得到预期效果。

0 0
原创粉丝点击