View类的getWidth()和getMeasuredWidth()的区别和应用

144 阅读4分钟

两个方法的源码如下:

View#getWidth

/**
 * Return the width of your view.
 *
 * @return The width of your view, in pixels.
 */
@ViewDebug.ExportedProperty(category = "layout")
public final int getWidth() {
    return mRight - mLeft;
}

View#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;
}

它们的区别是什么?

ViewgetWidth() 方法与 getMeasuredWidth() 方法在 Android 中用于获取视图的宽度,但它们返回的宽度信息在不同的布局阶段中有所不同。

  1. getMeasuredWidth()

    • getMeasuredWidth() 返回的是视图的测量宽度(measured width)。这个值是在布局的测量阶段(measure pass)决定的,这个阶段会确定视图需要多大的空间。测量宽度包含了视图本身的大小以及可能的状态位,比如MEASURED_STATE_TOO_SMALL。
    • 这个方法返回的宽度可能并不是视图最终的显示宽度,因为它是在布局的测量过程中确定的,而还没有完成布局的放置过程(layout pass)。
    • getMeasuredWidth() 返回的值是通过掩码 MEASURED_SIZE_MASK 处理过的,意味着它仅包含大小信息,而不包含状态信息。
  2. getWidth()

    • getWidth() 返回的是视图在布局的放置阶段(layout pass)之后的实际宽度。这个宽度是视图在屏幕上最终所展示的大小。
    • 这个值是通过计算视图的右边界 mRight 减去左边界 mLeft 得到的。在视图的父容器完成了放置过程后,这个宽度才会被确定下来。
    • 这个值可能会与 getMeasuredWidth() 返回的值不同,因为父容器在放置视图时可能会根据布局参数或者其它因素调整视图的大小和位置。

总之,getMeasuredWidth() 是在测量阶段使用的宽度值,而 getWidth() 是在布局完成后视图实际显示时的宽度值。开发者通常在视图已经被放置之后使用 getWidth() 来获取视图的实际大小,而在自定义视图或者布局过程中,可能需要使用 getMeasuredWidth() 来获取在测量阶段确定的尺寸信息。

这两个方法分别在什么时候,什么方法里会被调用?

getMeasuredWidth()getWidth() 在 Android 视图 (View) 的生命周期中的不同时刻和不同方法中被调用,具体取决于当前的布局阶段。下面是这两个方法通常被调用的情况:

  1. getMeasuredWidth()

    • 在视图树的测量阶段 (onMeasure() 方法) 被调用。在 onMeasure() 方法中,每个视图都需要根据其父视图传递的测量规格 (MeasureSpec) 来确定自己的尺寸,并使用 setMeasuredDimension() 方法存储测量结果。
    • 开发者可以在 onMeasure() 调用完成后或者在测量阶段结束后通过 getMeasuredWidth() 获取这个测量宽度。
    • 自定义视图时,可能需要调用 getMeasuredWidth() 来获取子视图的测量宽度以便进行一些特定的布局计算。
  2. getWidth()

    • 在视图树的布局阶段 (onLayout() 方法) 被调用。onLayout() 方法是父视图确定其子视图位置的地方,此时可以获取到子视图的实际大小。
    • 一旦布局阶段完成,可以在任何时刻通过 getWidth() 获取视图的实际宽度。通常这会发生在视图已经被放置在屏幕上之后,例如在 onLayout() 方法之后、在事件处理中、或者在动画中等。
    • 在任何需要知道视图最终大小的情况下,都应该使用 getWidth(),例如在绘制 (onDraw()) 方法中,或者在需要根据视图实际尺寸进行计算时。

举例来说,如果你正在编写一个自定义的视图或视图组,你可能会在 onMeasure() 方法中使用 getMeasuredWidth() 来决定子视图的大小,并在 onLayout() 方法中使用 getWidth() 来确定子视图的实际位置。如果你只是在应用中使用视图,且需要进行一些基于视图大小的操作,比如设置视图的动画,那么你应在布局完成后使用 getWidth()

需要注意的是,直到视图树的测量阶段和布局阶段完全完成之前,调用这些方法可能不会返回有效的值,因为视图尺寸尚未被确定。