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

时间:2011-08-04 18:14:20

标签: android layout measure

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

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

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

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

2 个答案:

答案 0 :(得分:79)

要触发自定义View的度量传递,您必须调用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();
}

答案 1 :(得分:1)

好吧,如果要更改View的内容,最终必须调用invalidate()。例如,您有一个带有文本“Text 1”的TextView。现在,您将同一TextView的文本更改为“文本2”。在这里,将调用invalidate。

所以基本上,当视图上的某些内容发生变化时,通常会调用invalidate方法,并调用measure()。

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

计算无效呼叫的数量。有很多。