我正在使用 AndroidX 的首选项库来管理我的应用程序的设置。我的
SettingsFragment
源自 PreferenceFragmentCompat
并加载以下布局:
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<androidx.preference.PreferenceScreen
android:key="screen_backup_key"
android:title="@string/local_database">
<androidx.preference.Preference
android:key="button_save_key"
android:title="@string/export" />
<androidx.preference.Preference
android:key="button_load_key"
android:title="@string/_import" />
</androidx.preference.PreferenceScreen>
<androidx.preference.Preference
android:key="screen_about"
android:title="@string/about" />
</androidx.preference.PreferenceScreen>
布局显示正确,但是当我单击嵌套的
PreferenceScreen
条目时,没有任何反应。它以前可以与 支持库中的
PreferenceScreen
一起使用,但现已弃用。
我希望看到这个嵌套的内容
PreferenceScreen
。我做错了什么?
AndroidX 的首选项库不再支持它。
使用 a 声明同一 XML 资源中的嵌套层次结构 不再支持嵌套
。你应该使用 而是嵌套的 Fragment 对象。PreferenceScreen
每个单独的屏幕都需要一个单独的
PreferenceFragmentCompat
。
如果您有大量偏好或不同类别,您 可以将它们显示在单独的屏幕上。每个屏幕应该是一个
有自己独立的层次结构。优先 然后,您的初始屏幕上可以链接到包含以下内容的子屏幕: 相关首选项。PreferenceFragmentCompat
你这样做:
要将屏幕与首选项链接,您可以在中声明
XML,或者您可以使用app:fragment
。设置完整包 启动时应启动的Preference.setFragment()
的名称 点击PreferenceFragmentCompat
,如下图:Preference
<Preference
app:fragment="com.example.SyncFragment"
.../>
这是进一步阅读的来源。
嵌套 ScreenPreference 无法在 AndroidX 中开箱即用。下面是一个处理嵌套 ScreenPreference 的 PreferenceActivity 替换示例。类似的方法可以仅用于片段。
注意以下事项:
addPreferencesFromResource()
。以下是如何使用它来替换 PreferenceActivity 作为基类:
PreferenceActivity
替换为 PreferenceActivityEx
。AndroidManifest.xml
中的继承 Activity。例如:android:theme="@style/Theme.AppCompat"
。androidx.preference
导入替换为 androidx.preference
。addPreferencesFromResource()
方法中的 onCreate()
调用之后处理首选项的代码移至新的覆盖 onPreferencesCreated()
方法。activity_preference_ex.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentContainerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/preferences_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
PreferenceActivityEx.java:
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
public class PreferenceActivityEx extends AppCompatActivity {
private RootPreferenceFragmentCompatEx mPreferencesFragment;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_preference_ex);
}
@Override
protected void onResume() {
super.onResume();
if (mPreferencesFragment == null)
throw new IllegalStateException("Must call 'addPreferencesFromResource()' in the 'onCreate()' method.");
}
protected Preference findPreference(@NonNull CharSequence key) {
if (mPreferencesFragment == null)
throw new IllegalStateException("Must call 'addPreferencesFromResource()' before 'findPreference()'");
return mPreferencesFragment.findPreference(key);
}
protected PreferenceScreen getPreferenceScreen() {
if (mPreferencesFragment == null)
throw new IllegalStateException("Must call 'addPreferencesFromResource()' before 'getPreferenceScreen()'");
return mPreferencesFragment.getPreferenceScreen();
}
protected void onPreferencesCreated() {
}
protected void addPreferencesFromResource(int preferencesResId) {
if (mPreferencesFragment != null)
throw new IllegalStateException("Only a single call to addPreferencesFromResource() is allowed.");
mPreferencesFragment = new RootPreferenceFragmentCompatEx(preferencesResId);
mPreferencesFragment.setOnPreferencesCreatedListener(this::onPreferencesCreated);
getSupportFragmentManager().beginTransaction()
.replace(R.id.preferences_container, mPreferencesFragment)
.commit();
}
public static abstract class PreferenceFragmentCompatEx extends PreferenceFragmentCompat {
@Override
public boolean onPreferenceTreeClick(@NonNull Preference preference) {
if (preference instanceof PreferenceScreen) {
PreferenceScreen preferenceScreen = (PreferenceScreen) preference;
// Create a new fragment to display the nested PreferenceScreen
NodePreferenceFragmentCompatEx fragment = new NodePreferenceFragmentCompatEx(preferenceScreen);
// Use the FragmentManager to replace the current fragment with the nested one
getParentFragmentManager().beginTransaction()
.replace(getId(), fragment)
.addToBackStack(null)
.commit();
return true;
}
return super.onPreferenceTreeClick(preference);
}
}
public static class NodePreferenceFragmentCompatEx extends PreferenceFragmentCompatEx {
private PreferenceScreen mPreferenceScreen;
public NodePreferenceFragmentCompatEx() {
}
public NodePreferenceFragmentCompatEx(PreferenceScreen preferenceScreen) {
mPreferenceScreen = preferenceScreen;
}
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
if (mPreferenceScreen != null)
setPreferenceScreen(mPreferenceScreen);
}
}
public static class RootPreferenceFragmentCompatEx extends PreferenceFragmentCompatEx {
private int mPreferencesResId;
private OnPreferencesCreatedListener mOnPreferencesCreatedListener;
public RootPreferenceFragmentCompatEx() {
}
public RootPreferenceFragmentCompatEx(int preferencesResId) {
mPreferencesResId = preferencesResId;
}
private void setOnPreferencesCreatedListener(OnPreferencesCreatedListener onPreferencesCreatedListener) {
mOnPreferencesCreatedListener = onPreferencesCreatedListener;
}
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable String rootKey) {
if (mPreferencesResId != 0) {
setPreferencesFromResource(mPreferencesResId, rootKey);
if (mOnPreferencesCreatedListener != null)
mOnPreferencesCreatedListener.onPreferencesCreated();
}
}
}
private interface OnPreferencesCreatedListener {
void onPreferencesCreated();
}
}