前提知识点:
1. 在一个类初始化时,即在构造函数当中是得不到View的实际大小的。getWidth()和getMeasuredWidth()得到的结果都是0,但是可以从onDraw()方法或者dispatchDraw()方法里面获得。可以通过调用invalidate()来执行onDraw()和dispatchDraw()方法。
2. 这两个方法所得到的结果的单位是像素即pixel
我们分析下这两个方法的不同,先看官方文档:
- getHeight 表示的是 View实际绘制出来的的大小
- getMeasuredHeight()是实际View的大小,也就是在父容器在计算当前view大小时,当前View的OnMeasure中设置的大小,与屏幕无关,与父容器大小无关。
- getMeasuredHeight()与getHeight()并没有直接关系,但是我们在layout的时候一般会遵循一定的原则
getMeasuredHeight取出的就是setMeasuredDimension的值
当然,上述其实只是一个概念,我们进一步的研究下,按照我们一个自定义View的过程中,我们会在onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法中完成测量后,必须调用View#setMeasuredDimension(int measuredWidth, int measuredHeight):
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);
}
其最终调用:
private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
mMeasuredWidth = measuredWidth;
mMeasuredHeight = measuredHeight;
mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
}
而我们getMeasuredHeight()取出来的就是mMeasuredHeight :
public final int getMeasuredHeight() {
return mMeasuredHeight & MEASURED_SIZE_MASK;
}
getHeight 取出的是父布局在绘制当前View的onLayout()中调用child.Layout(。。。)传入的参数
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.e("test", "MyViewGroup.onLayout left = " + l + " top = " + t + " right = " + r + " bottom = " + b);
View view = getChildAt(0);
int d = 200;
d = -d;
// d = t;
// view.layout(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight());
l = -100 + new Random().nextInt(100);
t = 0;
r = view.getMeasuredWidth() - 100;
b = view.getMeasuredHeight() - 100;
//view.getHeight= t- b;
view.layout(l, t, r, b);
}
public void layout(int l, int t, int r, int b) {
if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
}
int oldL = mLeft;
int oldT = mTop;
int oldB = mBottom;
int oldR = mRight;
boolean changed = isLayoutModeOptical(mParent) ?
setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
onLayout(changed, l, t, r, b);
mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnLayoutChangeListeners != null) {
ArrayList<OnLayoutChangeListener> listenersCopy =
(ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
int numListeners = listenersCopy.size();
for (int i = 0; i < numListeners; ++i) {
listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
}
}
}
mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
}
我们来看看getHeight():
public final int getHeight() {
return mBottom - mTop;
}