Android - reacting after initial layout
android
Solution
I've been successful using the OnGlobalLayoutListener.
It worked great on my Nexus S
final LinearLayout marker = (LinearLayout) findViewById(R.id.distance_marker);
OnGlobalLayoutListener listener = new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//some code using marker.getHeight(), etc.
markersContainer.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
};
marker.getViewTreeObserver().addOnGlobalLayoutListener(listener);
Problem
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 `Views` after the initial layout of a container (a `contentView`). The dimensions required in this case are of a View(Group) that is not predictable - might have multiple lines of text, minimum height to accommodate decoration, etc. I don't want to do it every on every layout pass (`onLayout`). The measurement I need is a from a deeply nested child, so overriding the `onLayout`/`onMeasure` of each container in between seems a poor choice. I'm not going to do anything that'll cause a loop (trigger-event-during-event). Romain Guy hinted once that we could just `.post` a `Runnable` in the constructor of a `View` (which AFAIK would be in the UI thread). This seems to work on most devices (on 3 of the 4 I have personally), but fails on Nexus S. Looks like Nexus S doesn't have dimensions for everything until it's done one pass per child, and does not have the correct dimensions when the `post`ed `Runnable`'s `run` method is invoked. I tried counting layout passes (in `onLayout`) and comparing to `getChildCount`, which again works on 3 out of 4, but a different 3 (fails on Droid Razr, which seems to do just one pass - and get all measurements - regardless of the number of children). I tried various permutations of the above (posting normally; posting to a `Handler`; casting `getContext()` to an `Activity` and calling `runOnUiThread`... same results for all). I ended up using a horrible shameful no-good hack, by checking the height of the target group against its parent's height - if it's different, it means it's been laid out. Obviously, not the best approach - but the only one that seems to work reliably between various devices and implementations. I know there's no built-in event or callback we can use, but is there a better way? TYIA /EDIT The bottom line for me I guess is that the Nexus S does not wait until after layout has completed when `.posting()` a `Runnable`, as is the case on all other devices I've tested, and as suggested by Romain Guy and others. I have not found a good workaround. Is there one?