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

AndroidLayoutMeasure

Android Problem Overview


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.

Android Solutions


Solution 1 - Android

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

Solution 2 - Android

Well, If you are changing a View's content, it will eventually have to call invalidate(). For example, you have a TextView with a text called "Text 1". Now, you change the text of the same TextView to "Text 2". Here aslo, invalidate will be called.

So basically, when something changes on the view, more often than not, you would expect the invalidate method to be called, and a corresponding call to the measure().

Look at the source code for TextView, for example. http://www.google.com/codesearch#uX1GffpyOZk/core/java/android/widget/TextView.java&q=TextView%20package:android&type=cs

Count the number of invalidate calls. There are quite a few.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionC NickView Question on Stackoverflow
Solution 1 - AndroidmoondroidView Answer on Stackoverflow
Solution 2 - AndroidKumar BibekView Answer on Stackoverflow