23

I need to measure total height of the ListView but it seems I'm constantly getting wrong values. I'm using this code:

public static void setListViewHeightBasedOnChildren(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null) {
        return;
    }

    int totalHeight = 0;
    int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(),
            MeasureSpec.AT_MOST);
    Log.w("DESIRED WIDTH", String.valueOf(listAdapter.getCount()));
    for (int i = 0; i < listAdapter.getCount(); i++) {
        View listItem = listAdapter.getView(i, null, listView);
        listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
        totalHeight += listItem.getMeasuredHeight();
        Log.w("HEIGHT"+i, String.valueOf(totalHeight));
    }

    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight
            + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    listView.setLayoutParams(params);
    listView.requestLayout();
}

Problem is that I'm receiving larger height than I should receive. Every list item is measured differently and all items have the same height so it definitely shouldn't do that. Height of each element is at least double of it's real height.

Thank you in advance.

edit1:

I have two ListViews and they both have items with 6-7 EditText fields. I show/hide ListView if user wants to write/delete values in EditText. Everything works well except when I want to show list, it takes a lot of space because method calculated ListView needs a lot of space. Because of that I have a lot of empty space below that ListView. Like three times more empty space that needed.

Cristiano
  • 3,099
  • 10
  • 45
  • 67
  • 1
    http://stackoverflow.com/questions/2312683/calculate-the-size-of-a-list-view-or-how-to-tell-it-to-fully-expand – RobinHood Feb 23 '13 at 11:36
  • Thank you but that doesn't work for me. I think I have this problem because I don't have just one ListView. There is probably some conflict with space coverage. – Cristiano Feb 23 '13 at 13:49

3 Answers3

53

Finally I've done it! This is the working code which measures ListView height and sets ListView in full size:

public static void getTotalHeightofListView(ListView listView) {

    ListAdapter mAdapter = listView.getAdapter();

    int totalHeight = 0;

    for (int i = 0; i < mAdapter.getCount(); i++) {
        View mView = mAdapter.getView(i, null, listView);

        mView.measure(
                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),

                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

        totalHeight += mView.getMeasuredHeight();
        Log.w("HEIGHT" + i, String.valueOf(totalHeight));

    }

    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight
            + (listView.getDividerHeight() * (mAdapter.getCount() - 1));
    listView.setLayoutParams(params);
    listView.requestLayout();

}
Cristiano
  • 3,099
  • 10
  • 45
  • 67
  • 7
    You should change the name of this method. Beginning it with "get" implies a return value other than void. – Sky Kelsey Aug 09 '13 at 01:45
  • In addition, this method is very slow to execute, I recommend running it only when the count of list items changes. – Sky Kelsey Aug 09 '13 at 02:01
  • 5
    You also need to add `listView.getPaddingTop()` and bottom. – njzk2 Jan 31 '14 at 13:58
  • I am working with a chat list view. What i think this way of getting total height would be very inefficient way. There could be so may elements in listview. – Gem Jul 21 '14 at 12:19
  • You also need to add totalHeight += listView.getDividerHeight(); for each list item. – Fedir Tsapana Aug 07 '14 at 13:44
  • 1
    Also assumes you have fixed height listView entries. The width of the containing ViewGroup isn't available in the above code, for it to be able to cope with variable height / **layout_height="wrap_content"** entries. – arober11 Apr 22 '15 at 14:45
  • 7
    It does not work when the cells have different heights – Sergei S Apr 30 '15 at 11:46
  • 1
    For list with variable height items, use this: http://stackoverflow.com/a/21638850/2511884 – Saket Nov 06 '15 at 10:15
  • 2
    This not working – IntoTheDeep Mar 16 '17 at 13:49
3

Try something like this :

listItem.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

  public void onGlobalLayout() {
    int listItemHeight = listItem.getHeight();
  }
});

If you want the height of the listView then try this :

listView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

  public void onGlobalLayout() {
    int listViewHeight = listView.getHeight();
  }
});

You could also check this : Calculate the size of a list view or how to tell it to fully expand

Community
  • 1
  • 1
lokoko
  • 5,785
  • 5
  • 35
  • 68
  • Thank you but that doesn't work for me. I made an edit in first post. I think the problem is with multiple lists. – Cristiano Feb 23 '13 at 13:58
  • If someone has a list containing items with the same height, then I guess doing list.LayoutParams = new LinearLayout.LayoutParams(fill_parent, thisFixedHeight * Count) is the way to go. No iteration anywhere. The real problem is to have something working with lists of lists of list. – Léon Pelletier Apr 06 '14 at 03:42
0

ListView caches the view items and reuses them. If you have a list view with 1000 items and only 6 visible, why, it's not worth rendering the 994 not showing.

Measuring the whole ListView would mean render every ListItem, seems a bit overkill.

I don't know what you are trying to achieve but there's probably a better way :)

Thibault D.
  • 10,041
  • 3
  • 25
  • 56
  • I don't have so many items :) I have two ListViews and they both have items with 6-7 EditText fields. I show/hide ListView if user wants to write/delete values in EditText. Everything works well except when I want to show list, it takes a lot of space because method calculated ListView needs a lot of space. Because of that I have a lot of empty space below that ListView. Like three times more empty space that needed. – Cristiano Feb 23 '13 at 11:38
  • But ListView doesn't know how you are going to use it so it's written this way. If you want the one of the listview to disappear and release the space on the screen for the other list to fill, use View.setVisibility(View.GONE) – Thibault D. Feb 23 '13 at 11:47
  • I'm using `View.setVisibility(View.GONE)` but when I show it again it takes really a lot of space, whole screen of empty space. I'm checking a link which @RobinHood posted. It seems they managed to do it by measuring it differently. – Cristiano Feb 23 '13 at 11:59