What triggers a View's measure() to be called

C Nick picture C Nick · Aug 4, 2011 · Viewed 38.1k times · Source

In my application I have an infinite loop on one of my View's onMeasure() overrides. Debugging the source code starting from a break point in my onMeasure, I am able to trace myself all the way up the stack trace up to the PhoneWindow$DecorView's measure() (top most class in my View Hierarchy), which gets called by ViewRoot.performTraversals(). Now from here if I keep stepping over, I eventually get the PhoneWindow$DecorView's measure() called again by a message in the Looper.loop() class. I'm guessing something has queued up a message that it needs to remeasure, like an invalidate.

My question is, what triggers that a measure call needs to occur on a View?

From my understanding of the layout/measure/draw process, this will only occur when the invalidate() method is called on a specific view, and that will trickle down and perform a layout/measure/draw pass for that view invalidated and all of its children. I would assume that somehow my top most View in my View Hierarchy is getting invalidated.

However, I've explicitly put a break point on every single invalidate call I have, and am not calling invalidate in some infinite manner. So I do not think that is the case. Is there another way to trigger a measure pass? Could something internally be triggering this? I'm kind of out of ideas after seeing that nothing is infinity invalidating.

Answer

moondroid picture moondroid · Dec 15, 2012

In order to trigger a measure pass for a custom View you must call the requestLayout() method. For example, if you are implementing a custom view that extends View and it will behave like a TextView, you could write a setText method like this:

/**
 * 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();
}