52

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

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

根据我对布局/测量/绘制过程的理解,这只会在特定视图上调用 invalidate() 方法时发生,并且会向下渗透并为该视图执行布局/测量/绘制通道无效和所有它的孩子。我会假设我的视图层次结构中的最顶层视图正在失效。

但是,我已经明确地在我拥有的每个 invalidate 调用上设置了一个断点,并且没有以某种无限的方式调用 invalidate。所以我认为情况并非如此。是否有另一种方法来触发测量通过?内部可能会触发这种情况吗?在看到没有什么是无限无效的之后,我有点没有想法。

4

2 回答 2

89

为了触发自定义视图的测量传递,您必须调用 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();
}
于 2012-12-15T12:58:08.867 回答
1

好吧,如果您要更改 View 的内容,它最终将不得不调用 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

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

于 2011-08-04T19:20:42.467 回答