Android笔记 View onMeasure

2018-04-10  本文已影响0人  blossom_6694

一、 onMeasure
onMeasure方法用于测量View 的大小。当子类重写这个方法时,必须调用setMeasuredDimension,不然会抛出 IllegalStateException。


protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),

            getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));

}

二、getSuggestedMinimumWidth
如果View没有设置背景则返回mMinWidth(对应布局中的miniWidth, 或view.setMinimumWidth) ,如果设置了背景就返回mMinWidth 和Drawable最小宽度两个值的最大值。


protected int getSuggestedMinimumWidth() {

    return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());

}

三、MeasureSpec
MeasureSpec 用来表示测量模式和大小,它是一个32位的int值,高两位为specMode (测量的模式),低30位为specSize (测量的大小),测量模式分为三种:

UNSPECIFIED:未指定模式,View想多大就多大,父容器不做限制,一般用于系统内部的测量。

AT_MOST:最大模式,对应于wrap_comtent属性,只要尺寸不超过父控件允许的最大尺寸就行。

EXACTLY:精确模式,对应于match_parent属性和具体的数值,父容器测量出View所需要的大小,也就是specSize的值。

四、getDefaultSize


public static int getDefaultSize(int size, int measureSpec) {

    int result = size;

    int specMode = MeasureSpec.getMode(measureSpec);

    int specSize = MeasureSpec.getSize(measureSpec);

    switch (specMode) {

    case MeasureSpec.UNSPECIFIED:

        result = size;

        break;

    case MeasureSpec.AT_MOST:

    case MeasureSpec.EXACTLY:

        result = specSize;

        break;

    }

    return result;

}

五、setMeasuredDimension


protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {

    boolean optical = isLayoutModeOptical(this);

    //判断当前view的LayoutMode是否为opticalbounds

    //ViewGroup 里面的方法, clipBounds就是默认值,不处理一些控件之间的“留白”,opticalBounds消除控件之间的留白

    if (optical != isLayoutModeOptical(mParent)) {

        Insets insets = getOpticalInsets();

        int opticalWidth  = insets.left + insets.right;

        int opticalHeight = insets.top  + insets.bottom;

        //如果是opticalBounds 模式,则需要加上“留白”的空间,如果是clipBounds模式,则要减去“留白”的空间

        measuredWidth  += optical ? opticalWidth  : -opticalWidth;

        measuredHeight += optical ? opticalHeight : -opticalHeight;

    }

    setMeasuredDimensionRaw(measuredWidth, measuredHeight);

}

private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {

    mMeasuredWidth = measuredWidth;

    mMeasuredHeight = measuredHeight;

    mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;

}

上一篇下一篇

猜你喜欢

热点阅读