1

I have an activity with a ListView in it. I need to determine the height of the list in pixels right after application start.

Every activity's onXXX() function I try to call ListView.getHight() in I get zero height.

If I call it in onResume() I get the correct value but only if I switch away from the app and then back to it, which, IMHO, contradicts with Android activity state diagram http://developer.android.com/images/activity_lifecycle.png

Please, advise.

jackhab
  • 17,128
  • 37
  • 99
  • 136
  • See this http://stackoverflow.com/questions/4142090/how-do-you-to-retrieve-dimensions-of-a-view-getheight-and-getwidth-always-r – user2340612 May 06 '13 at 22:03
  • @jackhab, how does this this apply to a widgets views which are handed through the `AppWidgetProvider` and `RemoteViews`? – Mridang Agarwalla Sep 27 '13 at 10:44

1 Answers1

0

You can't determine the height of the list in pixels right after the application start because the application doesn't know what that height should be then.

The app goes in sequence:

  • Acitivity Launched
  • onCreate()
  • onStart()
  • onResume()
  • Activity Running

I'm not sure how you interpret that any of those guarantee you an adequate measurement of a layout element.

The common Android UI doesn't just plop art out at specific locations and "poof" its always in the perfect place, because the Android UI is designed to be adaptive to whatever device it is running on. It has to layout the UI, balancing out constraints and alignments, even having to choose the appropriate drawables and layouts based on the size and pixel density of the display. Then it has to populate your list view.

You will not be able to get the height of any widget until the OS has calculated just what that height should be. That is not part of the view lifecycle.

Here is one place that should work (showing modified code from this famous solution:)

final ListView tv = (ListView)findViewById(R.id.your_widget);
ViewTreeObserver vto = tv.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

    @Override
    public void onGlobalLayout() {
        LayerDrawable ld = (LayerDrawable)tv.getBackground();
        ld.setLayerInset(1, 0, tv.getHeight() / 2, 0, 0);
        ViewTreeObserver obs = tv.getViewTreeObserver();
        obs.removeGlobalOnLayoutListener(this);
    }

});
Community
  • 1
  • 1
HalR
  • 11,411
  • 5
  • 48
  • 80
  • Thanks for the explanation. What do you think about JustDanyul's idea of using onWindowFocusChanged() (same famous thread)? And why do you cast ListView to TextView when getting its id? – jackhab May 07 '13 at 06:41
  • I know there [are cases](http://stackoverflow.com/a/11140421/793607) with onWindowFocusChanged() that don't measure properly. But this way has been reliable (unless you cast your widget improperly!!! sorry 'bout that) – HalR May 07 '13 at 13:31
  • Now that I discovered list height in the Listener I want to continue adding GUI elements which depend on this value. Where should I do this - inside the Listener? Seems a bit ugly to me. – jackhab May 07 '13 at 19:04
  • I agree, that could be a bit ugly. If you call an appropriately named method and keep it well contained it shouldn't be bad. – HalR May 07 '13 at 19:15