This question has been asked several times in various forms but I haven\'t found a definitive answer.
I need to be able to get dimensions and positions of descendant
My own experience with OnGlobalLayoutListener is that it does not always wait to fire until all of the child views have been laid out. So, if you're looking for the dimensions of a particular child (or child of a child, etc.) view, then if you test them within the onGlobalLayout() method, you may find that they reflect some intermediate state of the layout process, and not the final (quiescent) state that will be displayed to the user.
In testing this, I noticed that by performing a postDelayed() with a one second delay (obviously, a race condition, but this was just for testing), I did get a correct value (for a child of a child view), but if I did a simple post() with no delay, I got the wrong value.
My solution was to avoid OnGlobalLayoutListener, and instead use a straight override of dispatchDraw() in my top-level view (the one containing the child whose child I needed to measure). The default dispatchDraw() draws all of the child views of the present view, so if you post a call to your code that performs the measurements after calling super.dispatchDraw(canvas) within dispatchDraw(), then you can be sure that all child views will be drawn prior to taking your measurements.
Here is what that looks like:
@Override
protected void dispatchDraw(Canvas canvas) {
//Draw the child views
super.dispatchDraw(canvas);
//All child views should have been drawn now, so we should be able to take measurements
// of the global layout here
post(new Runnable() {
@Override
public void run() {
testAndRespondToChildViewMeasurements();
}
});
}
Of course, drawing will occur prior to your taking these measurements, and it will be too late to prevent that. But if that is not a problem, then this approach seems to very reliably provide the final (quiescent) measurements of the descendant views.
Once you have the measurements you need, you will want to set a flag at the top of testAndRespondToChildViewMeasurements() so that it will then return without doing anything further (or to make a similar test within the dispatchDraw() override itself), because, unlike an OnGlobalLayoutListener, there is no way to remove this override.