可以先看一下View / ViewGroup关于 getMeasuredWidth 这个函数的源码:
public final int getMeasuredWidth() {
return mMeasuredWidth & MEASURED_SIZE_MASK;
}
其中 mMeasuredWidth 是由我们在View的onMeasure阶段中使用 setMeasuredDimension 这个函数传入的。
setMeasuredDimension(int measuredWidth, int measuredHeight)
而 MEASURED_SIZE_MASK 是一个静态常量,我想它是用来限制mMeasuredWidth的大小吧。
public static final int MEASURED_SIZE_MASK = 0x00ffffff;
所以,我们的 getMeasuredWidth() 所返回的值与 该View / ViewGroup 在调用 setMeasuredDimension 后才会有一定的值,且由 setMeasuredDimension 决定返回值的大小。
接下来再看一下 View 关于 getWidth 这个函数的源码:
public final int getWidth() {
return mRight - mLeft;
}
而 mRight 和 mLeft 是在 View 的 setFrame / setOpticalFrame 函数中被赋值的。
protected boolean setFrame(int left, int top, int right, int bottom) {
boolean changed = false;
....
....
mLeft = left;
mTop = top;
mRight = right;
mBottom = bottom;
mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
....
....
return changed;
}
而 setFrame / setOpticalFrame 函数 在 View 的 layout中被调用:
public void layout(int l, int t, int r, int b) {
...
...
boolean changed = isLayoutModeOptical(mParent) ?
setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
...
...
}
什么时候我们的View会调用layout函数呢?一般在ViewGroup的onLayout函数中,我们会定位子View的位置,然后让子View调用layout函数,实现子View在ViewGroup的放置。
所以,我们的 getWidth() 所返回的值与 该View 在调用 layout 后才会有一定的值,且由 layout函数中的参数 决定返回值的大小。一般该View所在的ViewGroup进行onLayout阶段时会让View对象调用layout方法。
getMeasuredWidth 的返回值由 View 的 setMeasuredDimension 方法的决定。
getMeasuredWidth 的返回值由 View 的 layout 方法的决定。
一般来说,当 layout 方法传入的参数r、l 和 setMeasuredDimension 方法传入的 mMeasuredWidth 的关系不满足 r - l = mMeasuredWidth 时,getMeasuredWidth 和 getWidth 两者的返回值是不相同的。
在自定义 View / ViewGroup 的过程中,要根据时机的不同来调用 getMeasuredWidth 或 getWidth 函数。
getMeasuredHeight 和 getHeight 的区别类似。