Dynamically change the row height in a listview based on number of list items

tintin picture tintin · Jun 14, 2013 · Viewed 21.1k times · Source

I was creating an Android Application in which I use a ListView. The ListView consists of CheckedTextView list items. My activity contains an EditText at the top, a TextView below that and a Button at the bottom. The space between the TextView and the button is the area occupied by the ListView. Now, since my ListView contains rather few items, the entire space of the ListView is not occupied by them. Also the space left obviously varies across devices. What I want to know is if there is a way to alter the row height of ListView so that the entire space alloted to the ListView is covered. And also if there occurs a need to add some items the row height may adjust itself accordingly. I have provided some code snippets below so that it is easy to understand what my Layout is like.

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:background="#D0D0D0"
tools:context=".MainActivity" >

<Button
    android:id="@+id/addcourse"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:text="Add Course" />

<EditText
    android:id="@+id/coursenameet"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    android:ems="10"
    android:layout_marginBottom="2dp"
    android:layout_marginTop="2dp"
    android:hint="Course Name" 
    android:inputType="textCapWords" >

    <requestFocus />
</EditText>

<View
    android:id="@+id/divider"
    android:layout_width="match_parent"
    android:layout_height="3dp"
    android:layout_below="@+id/coursenameet"
    android:layout_marginBottom="5dp"
    android:layout_marginTop="5dp"
    android:background="@android:color/darker_gray" >
</View>

<TextView
    android:id="@+id/weekdaytv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_below="@+id/divider"
    android:layout_marginBottom="3dp"
    android:layout_marginTop="3dp"
    android:layout_centerHorizontal="true"
    android:text="Select weekdays for this Course" >
</TextView>

<ListView
    android:id="@+id/listView1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_above="@+id/addcourse"
    android:layout_below="@+id/weekdaytv"
    android:divider="#FFFFFF"
    android:dividerHeight="2px">

</ListView>

</RelativeLayout>

The items are CheckedTextViews that are implemented using BaseAdapter. The View method of BaseAdapter class is

public View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    int colorpos = position % colors.length;
    if(v == null){
        LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = vi.inflate(R.layout.listviewitem, null);
    }
    CheckedTextView newrow = (CheckedTextView) v.findViewById(R.id.checkedtextview);
    v.setBackgroundColor(colors[colorpos]);
    newrow.setTextColor(Color.BLACK);
    newrow.setText(items[position]);
    return v;
}

EDIT: Snippet from Main Activity

lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    adapter = new ItemsAdapter(MainActivity.this, weekdays, 6, lv.getBottom() - lv.getTop());
    lv.setAdapter(adapter);

    lv.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                long arg3) {
            CheckedTextView ctv = (CheckedTextView) arg1;
            adapter.toggle(ctv);
        }
    });

Answer

Nirmal picture Nirmal · Jun 14, 2013

Hi Create a class like this

public class Utility {

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

        int totalHeight = 0;
        int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(), MeasureSpec.AT_MOST);
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
            totalHeight += listItem.getMeasuredHeight();
        }

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


 }

Call this method at where do you want dynamically change the row height in a listview.

 Utility.setListViewHeightBasedOnChildren(YourListView);

For more Reference.. Hope this will help you.