Хорошо, я нашел 2 возможных, но странных решения.
Я все еще хотел бы знать, существует ли официальный способ сделать это, потому что оба решения довольно странные.
Решение 1
В XML-файле предпочтений основных настроек для каждого вложенного элемента PreferenceScreen
я поместил пустой тег Preference
.
preferences.xml
<PreferenceScreen
android:key="screen_preference" android:summary="Shows another screen of preferences"
android:title="Screen preference">
<Preference/>
</PreferenceScreen>
Я передаю ноль для второго аргумента setPreferencesFromResource
в новомфрагмент подэкрана.
Вот код (проект доступен здесь ):
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 {
supportFragmentManager.beginTransaction().replace(android.R.id.content, PrefsFragment2()).addToBackStack(null).commit()
return true
}
class PrefsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey)
}
}
class PrefsFragment2 : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences2, null)
}
}
}
Конечно, это нужно изменить, чтобы вы знали, какой фрагмент создать и добавить ...
Решение 2
Я использую обычный Preference
вместо каждого PreferenceScreen
и для каждого из них я выбираю добавить фрагмент по щелчку (проект доступен здесь ):
preferences.xml
<Preference
android:key="screen_preference" android:summary="Shows another screen of preferences"
android:title="Screen preference"/>
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
if (savedInstanceState == null)
supportFragmentManager.beginTransaction().replace(android.R.id.content, PrefsFragment()).commit()
}
class PrefsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey)
setPreferenceToOpenFragmentAsNewPage(findPreference("screen_preference"), PrefsFragment2::class.java)
}
private fun setPreferenceToOpenFragmentAsNewPage(pref: Preference, java: Class<out PreferenceFragmentCompat>) {
pref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
val fragment = java.newInstance()
val args = Bundle(1)
args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, pref.key)
fragment.arguments = args
activity!!.supportFragmentManager.beginTransaction().replace(android.R.id.content, fragment).addToBackStack(null).commit()
true
}
}
}
class PrefsFragment2 : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences2, null)
}
}
}
РЕДАКТИРОВАТЬ: небольшая модификация второго решения может сделать его лучше:
preferences.xml
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" android:title="Demo">
<Preference
android:fragment="com.example.user.myapplication.MainActivity$PrefsFragment2" android:key="screen_preference"
android:summary="Shows another screen of preferences" android:title="Screen preference"/>
</PreferenceScreen>
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
if (savedInstanceState == null)
supportFragmentManager.beginTransaction().replace(android.R.id.content, PrefsFragment()).commit()
}
class PrefsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences, rootKey)
setPreferenceToOpenFragmentAsNewPage(findPreference("screen_preference"))
}
private fun setPreferenceToOpenFragmentAsNewPage(pref: Preference) {
pref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
val clazz = Class.forName(pref.fragment)
val fragment: PreferenceFragmentCompat = clazz.newInstance() as PreferenceFragmentCompat
val args = Bundle(1)
args.putString(PreferenceFragmentCompat.ARG_PREFERENCE_ROOT, pref.key)
fragment.arguments = args
activity!!.supportFragmentManager.beginTransaction().replace(android.R.id.content, fragment).addToBackStack(null).commit()
true
}
}
}
class PrefsFragment2 : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences2, null)
}
}
}
Обратите внимание, что вам необходимо добавить это в правила Proguard:
-keepnames public class * extends androidx.preference.PreferenceFragmentCompat
Еще одно усовершенствование решения № 2 заключается в том, что оно может обходить все предпочтения самостоятельно:
class PrefsFragment : BasePreferenceFragment() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.preferences_headers, rootKey)
val preferenceScreen = preferenceScreen
val preferenceCount = preferenceScreen.preferenceCount
for (i in 0 until preferenceCount) {
val pref = preferenceScreen.getPreference(i)
val fragmentClassName = pref.fragment
if (fragmentClassName.isNullOrEmpty())
continue
pref.setOnPreferenceClickListener {
showPreferenceFragment(activity!!, fragmentClassName)
true
}
}
}
}
companion object {
@JvmStatic
private fun showPreferenceFragment(activity: FragmentActivity, fragmentClassName: String) {
val clazz = Class.forName(fragmentClassName)
val fragment: PreferenceFragmentCompat = clazz.newInstance() as PreferenceFragmentCompat
val fragmentsCount = activity.supportFragmentManager.fragments.size
val transaction = activity.supportFragmentManager.beginTransaction().replace(android.R.id.content, fragment)
if (fragmentsCount > 0)
transaction.addToBackStack(null)
transaction.commit()
}
}
РЕДАКТИРОВАТЬ: кажется, первое решение было правильным, но нужно изменить,Проверьте ответ здесь .Полный образец доступен здесь .