为什么使用AndroidX时嵌套的PreferenceScreen打不开?

问题描述 投票:0回答:2

我正在使用 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
。我做错了什么?

android kotlin android-preferences androidx preferencefragment
2个回答
7
投票

AndroidX 的首选项库不再支持它。

使用 a 声明同一 XML 资源中的嵌套层次结构 不再支持嵌套

PreferenceScreen
。你应该使用 而是嵌套的 Fragment 对象。

每个单独的屏幕都需要一个单独的

PreferenceFragmentCompat

如果您有大量偏好或不同类别,您 可以将它们显示在单独的屏幕上。每个屏幕应该是一个

PreferenceFragmentCompat
有自己独立的层次结构。优先 然后,您的初始屏幕上可以链接到包含以下内容的子屏幕: 相关首选项。

你这样做:

要将屏幕与首选项链接,您可以在中声明

app:fragment
XML,或者您可以使用
Preference.setFragment()
。设置完整包 启动时应启动的
PreferenceFragmentCompat
的名称 点击
Preference
,如下图:

<Preference
    app:fragment="com.example.SyncFragment"
    .../>

这是进一步阅读的来源


0
投票

嵌套 ScreenPreference 无法在 AndroidX 中开箱即用。下面是一个处理嵌套 ScreenPreference 的 PreferenceActivity 替换示例。类似的方法可以仅用于片段。

注意以下事项

  1. 活动布局没有利用大屏幕或可折叠设备。
  2. 片段不会持续存在(因此,如果屏幕旋转,它将返回到第一个首选项片段)。
  3. 只能调用一次
    addPreferencesFromResource()

以下是如何使用它来替换 PreferenceActivity 作为基类:

  1. PreferenceActivity
    替换为
    PreferenceActivityEx
  2. 将 AppCompatActivity 兼容主题添加到
    AndroidManifest.xml
    中的继承 Activity。例如:
    android:theme="@style/Theme.AppCompat"
  3. 将任何
    androidx.preference
    导入替换为
    androidx.preference
  4. 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();
    }
}

    
© www.soinside.com 2019 - 2024. All rights reserved.