How to configure ListView to automatically change its height?

I have three ListView widgets in the same LinearLayout . Something like this (I'm missing XML elements that are not relevant in this example):

 <LinearLayout> <ListView android:layout_width="fill_parent" android:layout_height="360dp"/> <ListView android:layout_width="fill_parent" android:layout_height="360dp"/> <ListView android:layout_width="fill_parent" android:layout_height="360dp"/> </LinearLayout> 

This makes the list have a height of 360 dip. Of course, this will be its height, even if there are several list items. So my question is how to make lists have automatic height? I want the height of the ListView take the exact size of the sum of all the items in the list.

+4
source share
5 answers

I implemented it this way (the code works, so this is more the source of the idea than the solution):

 package com.customcontrols; public class NoScrollListView extends ListView { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0) ); // here I assume that height being calculated for one-child only, seen it in ListView source which is actually a bad idea int childHeight = getMeasuredHeight() - (getListPaddingTop() + getListPaddingBottom() + getVerticalFadingEdgeLength() * 2); int fullHeight = getListPaddingTop() + getListPaddingBottom() + childHeight*(getCount()); setMeasuredDimension(getMeasuredWidth(), fullHeight); } } 

the calculation is not perfect, but it is close and still works. after that you just create a layout like this:

ScrollView com.customcontrol.NoScrollListView com.customcontrol.NoScrollListView com.customcontrol.NoScrollListView / Scrollview

ScrollView is crucial, as you can easily exhaust the borders of the screen.

PS. Calculation based on the rectum, since most of the calculation methods in ListView & Co are closed packages, which is a rather strange choice for public classes for the user interface.

+8
source

Instead of editing my previous answer, here is my actual version (after finally the thing became a problem and I had to fix it)

  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(MeasureSpec.UNSPECIFIED, 0)); int childHeight = getMeasuredHeight() - (getListPaddingTop() + getListPaddingBottom() + getVerticalFadingEdgeLength() * 2); // on a first run let have a space for at least one child so it'll trigger remeasurement int fullHeight = getListPaddingTop() + getListPaddingBottom() + childHeight*(getCount()); int newChildHeight = 0; for (int x = 0; x<getChildCount(); x++ ){ View childAt = getChildAt(x); if (childAt != null) { int height = childAt.getHeight(); newChildHeight += height; } } //on a second run with actual items - use proper size if (newChildHeight != 0) fullHeight = getListPaddingTop() + getListPaddingBottom() + newChildHeight; setMeasuredDimension(getMeasuredWidth(), fullHeight); } 

The hardest part is that onMeasure is called twice, first for an approximate layout, and then after the elements are added for an exact one, and both should return normal results.

+3
source

I found a solution to set ListView Height based on children , this work

 public static void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { // pre-condition return; } int totalHeight = 0; for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); listView.requestLayout(); } 
+3
source

You can try iterating through the ListView lines (see methods on the ViewGroup ), find their heights, sum them up and change the height of the ListView .

Having said that, I fully expect it to be terrible:

  • You need to consider the size of the screen, so your lists do not go beyond the screen.
  • It is necessary to consider changes in orientation.
  • You must consider any changes to your data (for example, deleting lines may require shortening your list)
  • Etc.

If your goal is to have a single list, but you have three data sources, combine the data and put them in one list. My MergeAdapter can help MergeAdapter .

+1
source

try this ... view a list of real heights

view xml code list

 <ListView android:id="@+id/my_listview" android:layout_width="match_parent" android:layout_height="match_parent" /> 

view java code list

  ListView lView = (ListView)findViewById(R.id.my_listview); lView.setAdapter(adapter); setListViewHeightBasedOnChildren(lView); 

setListViewHeightBasedOnChildren

 public static void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { return; } int totalHeight = 0; for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); listView.setLayoutParams(params); listView.requestLayout(); } 
+1
source

All Articles