7

I have an activity that has a ScrollView with a vertical LinearLayout that has two fragments that are PreferenceFragment instances as shown in the following layout file:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_height="wrap_content"
android:layout_width="match_parent"
>

<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:context="com.foo.app.SettingsActivity">

    <fragment
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:name="com.foo.app.SettingsFragment"
        android:id="@+id/fragment_settings"/>

    <fragment
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:name="com.foo.app.NotificationSettingsFragment"
        android:id="@+id/fragment_notification_settings"/>

</LinearLayout>

The problem is that the two fragments show up with just their PreferenceCategory title and the actual fragment UI is zero height and not visible. Oddly, it is possible to scroll each fragment individually and see the missing fragment UI. It is as if each Fragment is inside a ScrollView.

What I expected was for the two fragments to be sized to wrap their content and there be a single vertical slider to scroll the LinearLayout containing both fragments.

In case it is relevant, the two fragments extends android.preference.PreferenceFragment and do not define their layout in a layout file. Instead they load their Preference UI as follows:

    @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Load the preferences from an XML resource
    addPreferencesFromResource(R.xml.pref_notification);
}

TIA for your help.

Farrukh Najmi
  • 5,055
  • 3
  • 35
  • 54

4 Answers4

6

Remove the outer ScrollView. I had the same problem and that solved it for me.

I haven't found it in the documentation yet, but apparently the PreferenceFragment supplies its own ScrollView around the PreferenceScreen. Somehow that leads to a wrap_content height just large enough to show the first element (e.g. a category header).

  • 3
    I have multiple fragments that make up a custom SettingsActivity. If I remove the outer ScrollView then I get individual vertical Scroll bars in each of my custom settings fragments. This is undesirable as I just want a single vertical SCroll bar. So above solution does not address my need. Thanks for your help though. – Farrukh Najmi May 08 '14 at 13:33
  • 2
    any solution? I am in a similar situation where i have normal activity which in its layout has some pictures, buttons, at top and the bottom as well fragment or two in the middle. If size of this fragments is 0dp as recommended they don't take as much space that they need but they are scrollable (individually). What i want to achieve is actually to scroll whole screen at once and this fragments to take as much space as they need (so they are not scrollable separately of whole screen). At the moment I just set heights of this fragments to fix size (300dp for example). Not elegant at all ;( – Ewoks Apr 23 '15 at 08:02
  • See my answer below: https://stackoverflow.com/a/59479279/414037 – yonix Dec 25 '19 at 14:24
6

The question is quite old but in case someone else stumbles upon this, I've managed to find a solution. Just like @Ewoks mentioned, I had to settle for a fixed height as well (which didn't always play well with varying dpi of the devices).

But with the help of this code I managed to make the height dynamic, which wraps the content nicely.

In your PreferenceFragment class do as follows:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    if (getView() != null) {

        ListView listView = (ListView) getView().findViewById(android.R.id.list);
        Adapter adapter = listView.getAdapter();

        if (adapter != null) {
            int height = 0;
            //int height = listView.getPaddingTop() + listView.getPaddingBottom();

            for (int i = 0; i < adapter.getCount(); i++) {
                View item = adapter.getView(i, null, listView);

                item.measure(0, 0);
                height += item.getMeasuredHeight();
            }

            FrameLayout frame = (FrameLayout) getActivity().findViewById(R.id.content_frame); //Modify this for your fragment

            ViewGroup.LayoutParams param = frame.getLayoutParams();
            param.height = height + (listView.getDividerHeight() * adapter.getCount());
            frame.setLayoutParams(param);
        }
    }

}

Hope this helps someone!

Community
  • 1
  • 1
goat
  • 307
  • 3
  • 8
  • 1
    Worked perfect, saved me hours of debugging i'm sure! I was using dynamically added fragments instead of defined ones, so for anyone doing that, you can use `LinearLayout frame = (LinearLayout) getActivity().getFragmentManager().findFragmentByTag(getPrefTag()).getView();` to get the view of your dynamic fragment by tag, where #getPrefTag is a custom method that simply returns the defined tag that was used to add your fragment. – JCricket May 12 '16 at 23:55
1

Given that you can't remove the outer ScrollView, what worked for me is to change it to be a android.support.v4.widget.NestedScrollView and then in Activity's onCreate to run:

findViewById(R.id.nested_scroll_view).setNestedScrollingEnabled(false);
yonix
  • 11,665
  • 7
  • 34
  • 52
  • 1
    I had three `PreferenceFragment`s inside `ScrollView`, works well when changed it to `NestedScrollView`. It should be accepted answer. – marcinax Jun 04 '20 at 12:21
0

Try setting the the android:layout_weight in each fragment to roughly the size of each settings list. E.g.

<fragment
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="0.3"
    android:name="com.foo.app.SettingsFragment"
    android:id="@+id/fragment_settings"/>

<fragment
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="0.7"
    android:name="com.foo.app.NotificationSettingsFragment"
    android:id="@+id/fragment_notification_settings"/>
Paul Netherwood
  • 396
  • 2
  • 8