PreferenceFragmentCompat custom layout

Viewed 9202

I need a custom layout for my PreferenceFragmentCompat. In the docs for PreferenceFragmentCompat it seems that you can possibly inflate and return a view in onCreateView().

However a NPE results:-

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setAdapter(android.support.v7.widget.RecyclerView$Adapter)' on a null object reference
                                                                       at android.support.v7.preference.PreferenceFragmentCompat.bindPreferences(PreferenceFragmentCompat.java:511)
                                                                       at android.support.v7.preference.PreferenceFragmentCompat.onActivityCreated(PreferenceFragmentCompat.java:316)
                                                                       at com.cls.example.MyPrefFrag.onActivityCreated(MyPrefFrag.java:42) 

After I checked the source of PreferenceFragmentCompat:onCreateView I found the following piece of code :-

 RecyclerView listView = this.onCreateRecyclerView(themedInflater, listContainer, savedInstanceState);
 if(listView == null) {
    throw new RuntimeException("Could not create RecyclerView");
 } else {
    this.mList = listView;   //problem
    ...
    return view;
 }

So if you override onCreateView() and return a custom layout the onCreateRecyclerView() is not called plus the RecyclerView private field mList will not be set. So the NPE on setAdapter() results.

Should I assume that having a custom layout is not feasible for PreferenceFragmentCompat ?

2 Answers

I had the same problem, however my requirements were a bit different, I just needed to show a layout above the settings list, so I did this

<NestedScrollView>
  <ConstrainLayout>
    <CustomView>
    <SettingsFragmentHolder/>
  </ConstraintLayout>
</NestedScrollView>

Then later in code I just do this

FragmentManager.beginTransaction().replace(holder, PreferencesFragment()).commit()

One thing to note is that, preferences fragment has its own scrollview or a list, that will cause the NestedScrollView to scroll to the beginning of PreferencesFragment layout, to fix that add this to the parent layout of the PreferencesFragment, in this case it is ConstraintLayout

android:descendantFocusability="beforeDescendants"
android:focusableInTouchMode="true"

That will stop the default scrolling behavior

Related