什么触发了View的measure()被调用

C N*_*ick 43 layout android measure

在我的应用程序中,我在View的onMeasure()覆盖之一上有一个无限循环.从我的onMeasure中的断点开始调试源代码,我能够一直跟踪堆栈跟踪到PhoneWindow $ DecorView的measure()(我的View Hierarchy中最顶级的类),它由ViewRoot调用.performTraversals().现在,如果我继续踩过来,我最终会通过Looper.loop()类中的消息再次调用PhoneWindow $ DecorView的measure().我猜是有些东西排队了一条需要重新测量的消息,比如无效.

我的问题是,什么触发了一个度量调用需要在View上发生?

根据我对布局/测量/绘制过程的理解,这只会在特定视图上调用invalidate()方法时发生,并且会逐渐减少并执行该视图无效的布局/测量/绘制过程以及所有它的孩子.我会假设我的视图层次结构中的最顶层视图无效.

但是,我已经明确地对每一个无效的调用设置了一个断点,并且没有以某种无限的方式调用invalidate.所以我认为不是这样的.是否有其他方法可以触发测量通过?内部可以触发这个吗?在看到无限无效之后,我有点想法了.

moo*_*oid 81

要为自定义视图触发度量传递,您必须调用requestLayout()方法.例如,如果要实现扩展View的自定义视图,它的行为类似于TextView,则可以编写如下的setText方法:

/**
 * Sets the string value of the view.
 * @param text the string to write
 */
public void setText(String text) {
    this.text = text;

            //calculates the new text width
    textWidth = mTextPaint.measureText(text);

    //force re-calculating the layout dimension and the redraw of the view
    requestLayout();
    invalidate();
}
Run Code Online (Sandbox Code Playgroud)

  • Invalidate只会导致再次绘制视图.requestLayout将导致它被布局和绘制. (7认同)
  • 你真的需要`requestLayout()`和`invalidate()`吗?我的印象是`invalidate()`会同时做到这两点. (5认同)
  • 这不回答这个问题.问题是什么触发而不是如何触发. (2认同)

Kum*_*bek 1

好吧,如果您要更改视图的内容,它最终必须调用 invalidate()。例如,您有一个 TextView,其中包含名为“Text 1”的文本。现在,您将同一 TextView 的文本更改为“Text 2”。这里同样会调用 invalidate 。

所以基本上,当视图上发生某些变化时,您通常会期望调用 invalidate 方法,以及对measure() 的相应调用。

例如,查看 TextView 的源代码。 http://www.google.com/codesearch#uX1GffpyOZk/core/java/android/widget/TextView.java&q=TextView%20package:android&type=cs

计算无效调用的数量。有不少。