1

I am currently trying to use a preference fragment within a Navigation Drawer. There are multiple preference fragments that may populate a frame layout, all of which could be of a different size and may not be the full height of the parent. For this reason I was wanting to use wrap_content for the frame layout height, but as preference fragment extends from ListView this causes problems (reference ListView Wrap Content). wrap_content does provide the desired result, although I can see that OnBindView is being called continuously, which highly inefficient and causes my data binding methods to be called all the time.

Has anyone got any simple out the box solutions I could try? Or would this be a case for a custom View where I would measure the children of the fragment and set the height at run time? Any help on this would be much appreciated.

The layout below shows the drawer layout which is included in the main layout.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:orientation="horizontal"
    android:padding="20dp">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <RadioGroup
            android:id="@+id/drawer_radio"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <RadioButton
                android:id="@+id/drawer_radio_button_0"
                style="@style/ButtonDrawer"
                android:background="@drawable/fft_button"
                android:button="@null"
                android:contentDescription="@string/image_button"/>

            <RadioButton
                android:id="@+id/drawer_radio_button_1"
                style="@style/ButtonDrawer"
                android:background="@drawable/trigger_button"
                android:button="@null"
                android:contentDescription="@string/image_button"/>

        </RadioGroup>
    </LinearLayout>
    <FrameLayout
        android:id="@+id/drawer_preference_list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        tools:layout="@android:layout/simple_list_item_1"
        android:background="@drawable/floating_preference_background_shape"/>

</LinearLayout>
Community
  • 1
  • 1

1 Answers1

0

Ok, so I think I found a good solution so I thought I'd post it for others to use. The way I had to do this was to extend from PreferenceFragment and do some measurements at run time, in which I can use to resize the listView.

I did this with the following.

public class PreferenceFragmentHeightWrap extends PreferenceFragment {

/**
 * We can guarantee that all children will be in the adaptor list by this point
 */
@Override
public void onResume() {
    super.onResume();
    setListViewHeightBasedOnItems(getView());
}

/**
 * Sets ListView height dynamically based on the height of the items.
 *
 * @return true if the listView is successfully resized, false otherwise
 */
public boolean setListViewHeightBasedOnItems(View view) {

    ListView listView = (ListView) view.findViewById(android.R.id.list);
    ListAdapter listAdapter = listView.getAdapter();
    if(listAdapter != null) {

        int numberOfItems = listAdapter.getCount();
        // Get total height of all items.
        int totalItemsHeight = 0;
        for(int itemPos = 0; itemPos < numberOfItems; itemPos++) {
            View item = listAdapter.getView(itemPos, null, listView);
            item.measure(0, 0);
            totalItemsHeight += item.getMeasuredHeight();
        }

        // Get total height of all item dividers.
        int totalDividersHeight = listView.getDividerHeight() *
                (numberOfItems - 1);

        // Set list height.
        ViewGroup.LayoutParams params = view.getLayoutParams();
        params.height = totalItemsHeight + totalDividersHeight + listView.getPaddingBottom()
                + listView.getPaddingTop();
        view.setLayoutParams(params);

        return true;

    } else {
        return false;
    }

}

Hopefully this will make sense and feel free to comment if you see anything untoward.