Background
On previous versions of support library, we could use headers in order to have a main-menu screen of settings, that each would open a new settings screen (fragment) .
The problem
Now headers are gone (as written here) for some time, and I think it became worse on android-x :
One thing you’ll note isn’t in here is preference headers and you’d be totally right. However, that doesn’t mean a single list of preferences need to span a 10” tablet screen. Instead, your Activity can implement OnPreferenceStartFragmentCallback (link) to handle preferences with an app:fragment attribute or OnPreferenceStartScreenCallback (link) to handle PreferenceScreen preferences. This allows you to construct a ‘header’ style PreferenceFragmentCompat in one pane and use those callbacks to replace a second pane without working in two separate types of XML files.
Thing is, I fail to use these on the new android-x API.
Each fragment has its own preferences XML tree (using setPreferencesFromResource
within onCreatePreferences
) , but each solution I've come up with has either done nothing, or crashed.
To put it in a visual way, this is what I'm trying to achieve :
Since there are multiple sub settings screens, it would be very messy to have all of the preferences of all of them be put in one XML file of the main settings screen.
What I've tried
Only thing I've succeeded, is to use the PreferenceScreen to hold the preferences of the sub-screen that's supposed to be shown.
Here's a working code (project available here) of such a thing :
preferences.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="Demo">
<PreferenceScreen
android:key="screen_preference" android:summary="Shows another screen of preferences"
android:title="Screen preferenc">
<CheckBoxPreference
android:key="next_screen_checkbox_preference"
android:summary="Preference that is on the next screen but same hierarchy"
android:title="Toggle preference"/>
</PreferenceScreen>
</PreferenceScreen>
MainActivity.kt
class MainActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
if (savedInstanceState == null)
supportFragmentManager.beginTransaction().replace(android.R.id.content, PrefsFragment()).commit()
}
override fun onPreferenceStartScreen(caller: PreferenceFragmentCompat, pref: PreferenceScreen): Boolean {
val f = PrefsFragment()
val args = Bundle(1)
args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, pref.key)
f.arguments = args
supportFragmentManager.beginTransaction().replace(android.R.id.content, f).addToBackStack(null).commit()
return true
}
class PrefsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey)
}
}
}
But, as I wrote, this is not what I'm trying to do. I want to have multiple classes that extend PreferenceFragmentCompat, each with its own XML file, which will be opened from the main one.
Here are the things I've tried (and failed) :
Set a "android:fragment" for the
PreferenceScreen
, to point to the new fragments classes, similar to headers. This didn't do anything at all.Use a normal Preference and have click listener for it, that will do the fragment transaction as shown on the original code. This caused a crash that says something like "Preference object with key screen_preference is not a PreferenceScreen" .
Tried to avoid using ARG_PREFERENCE_ROOT , but had same crash as on #2 .
As suggested here, I tried to return
this
in functiongetCallbackFragment
, but this didn't help at all.
The question
Is it possible to have the main settings fragment just let the user to navigate to the other fragments, while not having any other preferences that belong to them (inside preferences.xml
) ?
How?
onPreferenceStartFragment
available anywhere. Can you please show how you got to use it? Also, the solution of1.1.0-alpha01
seems to work well (without the need foronPreferenceStartFragment
). But be careful when using this alpha version. It seems to cause crashes : issuetracker.google.com/issues/120687886 – Grith