Calculate the size of a list view or how to tell it to fully expand

Viewed 40709

I am currently trying to use a ListView inside of a ScrollView. I know from what I've read that this is looked down upon, but I'm trying to get the ListView to expand completely by showing all of its rows so there is no need for it to scroll. I've been struggling, however, with how to tell the ListView to completely expand to show all of its rows since it needs a defined height. How do I calculate the height of a fully expanded ListView before it is drawn?

This problem mainly stems from the fact that you can't put a scrollable view inside of another scrollable view. I am okay with the fact that the ListView won't be able to scroll as long as I can make it expand to show all of its rows. I cannot do this, however, without being able to give it a defined height, which it seems I would need to calculate.

My full layout is too big for the "physical" screen and needs to scroll in order to show the rest of the list and buttons at the bottom. I'm trying to get across that the "virtual" screen is too big to fit on one screen even without the ListView there.

12 Answers

If you want a ListView which won't scroll couldn't you just use a LinearLayout?

You should not place your ListView in a ScrollView. The ListView is already scrollable.

The ListView should expand fully by default, if it is the only thing in the layout.

If it is not the only thing in the layout, and you want the ListView to expand to take up all available space, set the layout_weight on the ListView to 1, where all other layout_weight=0.

<LinearLayout android:layout_width="fill_parent" 
             android:layout_height="fill_parent" orientation="vertical">
  <TextView id="@+id/title" 
             android:layout_width="wrap_content" 
            android:layout_height="wrap_content"/>
  <ListView id="@+id/listView" 
            android:layout_width="fill_parent" 
            android:layout_height="0dp" 
            android:layout_weight="1"/>
</LinearLayout>

Edit: The ListView is really designed to be scrollable...the screen layout you have in your screenshot doesn't really seem like the "android way".

However, if your really want to circumvent that, you could try inflating one of the rows, get its minHeight, and multiply that by the number of items in the ListView adapter.

LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.label_value_row, null, false);
int height = adapter.getCount() * view.getMinHeight();

I've been researching on how to do this, and although the question has already been answered, I'd like to provide a solution that I think is better:

Looking at the ListView's source code you can see the following inside the onMeasure(...) code:

if (heightMode == MeasureSpec.AT_MOST) {
     // TODO: after first layout we should maybe start at the first visible position, not 0
     heightSize = measureHeightOfChildren(widthMeasureSpec, 0, NO_POSITION, heightSize, -1);
}

So simply call the listView's measure and pass MeasureSpec.AT_MOST for the height instead of the usual MeasureSpec.UNSPECIFIED.

I do the following to measure a listview and place it inside a popup-window:

    int widthMeasureSpec = MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels, MeasureSpec.EXACTLY);
    int heightMeasureSpec = MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels, MeasureSpec.AT_MOST);
    mCatalogView.measure(widthMeasureSpec, heightMeasureSpec);

    mPopup.setWidth(mCatalogView.getMeasuredWidth());
    mPopup.setHeight(mCatalogView.getMeasuredHeight());

I ended up overriding onDraw() of the ListView and calculating the average height of the visible rows in the view then estimating the actual height of the list based on how many items are in the adapter. This estimating happens a couple of times until all of the rows are visible.

Related