Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListView header ignores layout_height

I inflate this view, and add it to my ListView as a header. I am trying to make it 500dp high (hard coded, for the sake of this example)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
              android:layout_width="match_parent" android:background="@drawable/repeat_background"
              android:layout_height="500dp">

    <ImageView android:id="@+id/filter_menu" android:src="@drawable/ic_sort"
               android:layout_gravity="center_vertical" android:padding="8dp"
               android:layout_weight="0"
               android:layout_width="wrap_content" android:layout_height="wrap_content"
               android:onClick="showPopup"/>

</LinearLayout>

The ListView does not respect the authoritah of its header and wraps it on its content. Can anyone please explain what happens?

like image 314
Glenn Bech Avatar asked Sep 12 '14 15:09

Glenn Bech


1 Answers

The key to understand what's going on is figuring out how ListView headers and footers are implemented. They're a trick: the moment you add the first header or footer to your ListView, your ListAdapter is wrapped in a HeaderViewListAdapter (happens on line 270 of ListView.java). The HeaderListViewAdapter is a list adapter that tweaks count and position values to include the headers and footers; headers and footers become normal list items that the system manages for you.

If you look at line 207 of HeaderListViewAdapter.java, you'll see that the getView implementation ignores the parent view when adding a header or footer. This has the effect that its mLayoutParams doesn't get initialized from XML (can't really point you to the source code, just something I've found out over time).

If you then follow the calls to getView for a bit, past line 2237 of AbsListView.java, and follow the calls for obtainView for a bit and search for LayoutParams (which is what I just did) you end up at line 1182 of ListView.java. Here you see that, if the layout params are null when the child view is measured, it calls out to generateDefaultLayoutParams(), which is implemented on line 6065 of AbsListView.java:

@Override
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
    return new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.WRAP_CONTENT, 0);
}

...and that's where your WRAP_CONTENT is coming from.

As an easy work-around, just wrap the <LinearLayout/> of your XML inside a <FrameLayout/>. Keep the 500dp on the LinearLayout and make the FrameLayout have a layout height of WRAP_CONTENT (which will get ignored anyway).

like image 190
Barend Avatar answered Nov 03 '22 19:11

Barend