ViewGroup的onMeasure探讨

如果LinearLayout的宽度是wrap_content,里面TextView 的宽度是match_parent,那么TextView和LinearLayout的宽度测量要怎么测量,



        

    

    

        

    

widthMeasureSpec 与 heightMeasureSpec是一个int型的变量,高2位用来封装MeasureMode,剩下的封装parent能够容纳的最大值,MeasureSpec.getMode(widthMeasureSpec),MeasureSpec.getSize(widthMeasureSpec)。如果ViewGroup的宽度是EXACTLY(match_parent,100dp)直接使用固定值来测量,就是100dp或者是parent的宽度,如果是wrap_content,就需要测量childView的宽度,测量时包括childView的排列方(LinearLayout,RelativeLayout等)。

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int count = getChildCount();

        int maxHeight = 0;
        int maxWidth = 0;
        int measuredChildState = 0;

        // Find rightmost and bottom-most child
        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);
            if (child.getVisibility() != GONE) {
                measureChild(child, widthMeasureSpec, heightMeasureSpec);
                maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
                maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
                measuredChildState = combineMeasuredStates(measuredChildState,
                        child.getMeasuredState());
            }
        }

        // Account for padding too
        maxWidth += mPaddingLeft + mPaddingRight;
        maxHeight += mPaddingTop + mPaddingBottom;

        // Check against our minimum height and width
        maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
        maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());

        setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, measuredChildState),
                resolveSizeAndState(maxHeight, heightMeasureSpec,
                        measuredChildState<
 protected void measureChild(View child, int parentWidthMeasureSpec,
            int parentHeightMeasureSpec) {
        final LayoutParams lp = child.getLayoutParams();

        final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                mPaddingLeft + mPaddingRight, lp.width);
        final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
                mPaddingTop + mPaddingBottom, lp.height);

        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }

计算childView的时候,传递进了parentWidthMeasureSpec,我们继续往下跟。

  public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
        int specMode = MeasureSpec.getMode(spec);
        int specSize = MeasureSpec.getSize(spec);
        int size = Math.max(0, specSize - padding);
        int resultSize = 0;
        int resultMode = 0;
        switch (specMode) {

      case MeasureSpec.AT_MOST:
            if (childDimension >= 0) {
                // Child wants a specific size... so be it
                resultSize = childDimension;
                resultMode = MeasureSpec.EXACTLY;
            } else if (childDimension == LayoutParams.MATCH_PARENT) {
                // Child wants to be our size, but our size is not fixed.
                // Constrain child to not be bigger than us.
                resultSize = size;
                resultMode = MeasureSpec.AT_MOST;
            } else if (childDimension == LayoutParams.WRAP_CONTENT) {
                // Child wants to determine its own size. It can't be
                // bigger than us.
                resultSize = size;
                resultMode = MeasureSpec.AT_MOST;
            }
            break;

        ...
    }

回到刚才的问题上,LinearLayout的宽度是wrap_content对应AT_MOST,childDimension对应MATCH_PARENT,所以在这里即使设置了TextView的宽度是match_parent,实际上系统帮我们转换成了wrap_content模式,宽度是parent的specSize,parent的宽度实际上是他的parent的能给他的最大宽度。
]

你可能感兴趣的:(ViewGroup的onMeasure探讨)