阅读 206

android 中 getWidth() 和getMeasureWidth()的区别

别BB,看源码

getWidth()

  • View 类
     * Return the width of your view.
     *
     * @return The width of your view, in pixels.
     */
    public final int getWidth() {
        return mRight - mLeft;
    }

复制代码
  • so ,mRight和 mLeft是什么东东?

  • 看源码

  /**
     * The distance in pixels from the left edge of this view's parent
     * to the left edge(边缘) of this view.
     * {@hide}
     * 当前view的做左边缘到父view左便于的像素距离
     */
    protected int mLeft;
    /**
     * The distance in pixels from the left edge of this view's parent
     * to the right edge of this view.
     * {@hide}
     * 同理
     */
    protected int mRight;
复制代码
  • 所以,这只是一个通过加减得到的一个相对值,并不是真正测量得到的尺寸;

getMeasuredWidth

     * Like {@link #getMeasuredWidthAndState()}, but only returns the
     * raw width component (that is the result is masked by
     * {@link #MEASURED_SIZE_MASK}).
     *
     * @return The raw measured width of this view. 原始宽度
     *
     */
    public final int getMeasuredWidth() {
        return mMeasuredWidth & MEASURED_SIZE_MASK;
    }
复制代码
  • 这里有两个变量,一个是 mMeasuredWidth,一个是 MEASURED_SIZE_MASK

    /**
     * Bits of {@link #getMeasuredWidthAndState()} and
     * {@link #getMeasuredWidthAndState()} that provide the actual(真实的) measured size.
     */
    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
复制代码

MEASURED_SIZE_MASK 是一个16进制的树,这里需要说明一下,view 的测量结果,它封装在:MeasureSpec类中,主要包含测量结果测量模式,有三种,分别是:MeasureSpec.UNSPECIFIED,MeasureSpec.AT_MOST,MeasureSpec.EXACTLY,MeasureSpec通过makeMeasureSpec() 方法将模式大小,封装在了一起,一个int值,高2位是测量模式,低30位是view的尺寸;

mMeasuredWidth 的值是怎么设置上的;

  • 流程子view 的 onMeasure()---->setMeasuredDimension()----->setMeasuredDimensionRaw()

  • 第一步 :setMeasuredDimension();

  /**
     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
     * measured width and measured height. Failing to do so will trigger an
     * exception at measurement time.</p>
     * 这个方法必须在onMeasure(int, int)中调用
     *
     * @param measuredWidth The measured width of this view.  May be a complex
     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
     * {@link #MEASURED_STATE_TOO_SMALL}.
     * @param measuredHeight The measured height of this view.  May be a complex
     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
     * {@link #MEASURED_STATE_TOO_SMALL}.
     */
    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;
        }
        // 设置view的原始尺寸
        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
    }

复制代码

第二步:setMeasuredDimensionRaw();

    /**
    * 
     * Sets the measured dimension without extra processing for things like optical bounds.
     * Useful for reapplying consistent values that have already been cooked with adjustments
     * for optical bounds, etc. such as those from the measurement cache.
     *
     * @param measuredWidth The measured width of this view.  May be a complex
     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
     * {@link #MEASURED_STATE_TOO_SMALL}.
     * @param measuredHeight The measured height of this view.  May be a complex
     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
     * {@link #MEASURED_STATE_TOO_SMALL}.
     */
    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
        mMeasuredWidth = measuredWidth;
        mMeasuredHeight = measuredHeight;

        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
    }

复制代码
  • 包含了复杂的掩码操作
  • mMeasuredWidth 和 mMeasuredHeight 里面包含了view的真实尺寸,还有测量模式;
  • 所以,我getMeasuredWidth() 获取的是 onMeasure() 以后的尺寸;
文章分类
Android
文章标签