以编程方式将首选项添加到 PreferenceScreen 中的特定位置

Add preferences to specific places in PreferenceScreen programmatically

我正在以编程方式填充我的部分偏好设置。这很好用。不幸的是,当用户更改某些偏好(想想 'add a new alarm' 偏好)时,必须添加新的偏好。这也很好,当我使用 PreferenceCategories 时(因为新的是在这样的末尾添加的,所以 myPreferenceCategory.addPreference(newPreference) 可以解决问题)。但是我该怎么做才能以编程方式将首选项添加到任何特定位置(不仅仅是通常 categories/the prefScreen 的末尾??


我尝试使用某种 "invisible" PreferenceCategory,通过将 android:layout="my_custom_invis_layout" 设置为

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/my_custom_invis_layout"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:paddingBottom="0dp"
  android:paddingTop="0dp"
  android:layout_marginTop="0dp"
  android:layout_marginBottom="0dp"/>

不幸的是,这些填充和边距似乎对空类别的最小值 space 没有影响(但使用正值这样做,这 - 原因 - 没有帮助)。


我也尝试通过

取消布局
<PreferenceCategory
    android:layout="@null">

但这只是扩大了 space 类别对其他偏好所具有的类别的影响。


不幸的是,到目前为止,SO 并没有帮助我解决这个问题。如果有人能指出 "add a preference A below preference B" 之类的内容或如何创建一个完全不使用 space 的类别(因为这也可以解决我的问题),我将非常高兴。

我看到这个问题已经很老了,但是由于我遇到了类似的问题并设法解决了它,所以我认为无论如何发帖都没有什么坏处。 我解决这个问题的方法是从一开始就在 xml 中添加首选项(在我的例子中是需要在其他类别中的特定位置添加的类别),如果还不需要,则以编程方式将其删除。之后(以编程方式)将其放回原位时,它会出现在删除之前的相同位置。还没有尝试过您的特定情况(单个首选项需要进入类别中的特定位置),但我敢打赌它的工作方式相同。

public class PreferencesFragment extends PreferenceFragmentCompat {
    private SharedPreferences mSharedPreferences;
    private PreferenceCategory mPreferenceCategory;

    @Override
    public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
        addPreferencesFromResource(R.xml.preferences);
        mPreferenceCategory = (PreferenceCategory) findPreference("preferenceCategoryKey");

        if (preferenceNotRequiredYet) {
            removePreferenceCategory();
        }

        // an I have a SharedPreferenceListener attached that calls
        // addPreferenceCategory when I need to add it back
    }

    private void removePreferenceCategory() {
        PreferenceScreen parentScreen = (PreferenceScreen) findPreference("parent_screen_key");
        parentScreen.removePreference(mPreferenceCategory);
    }

    private void addPreferenceCategory() {
        PreferenceScreen parentScreen = (PreferenceScreen) findPreference("parent_screen_key");
        parentScreen.addPreference(mPreferenceCategory);
    }
}

好的,我已经尝试过使用 Preferences#setOrder(int) 的其他方法。 (我将之前的答案留在那里,因为对于某些用例,它可能是更简单的解决方案。)这个是否更适合您的需求?

public class PreferencesFragment extends PreferenceFragmentCompat {
    private SharedPreferences mSharedPreferences;
    PreferenceCategory mMyPreferenceCategory;
    // ArrayList to keep track of the currently added Preferences
    ArrayList<Preference> mPreferenceList = new ArrayList<>();
    // this counter only serves for name-giving of the added
    // Preferences in this example
    int mCounter = 0;

    @Override
    public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
        addPreferencesFromResource(R.xml.preferences);
        mMyPreferenceCategory = (PreferenceCategory) findPreference("preferenceCategoryKey");
        addPreference(null);
    }

    // adds a Preference that is inserted on the position of the
    // clicked Preference, moving the clicked Preference - and all
    // Preferences after - one position down
    private void addPreference(Preference pref) {
        int order = 0;
        if (pref != null) {
            order = pref.getOrder();
        }
        for (Preference preference : mPreferenceList) {
            int oldOrder = preference.getOrder();
            if (oldOrder >= order) {
                preference.setOrder(oldOrder+1);
            }
        }
        Preference newPreference = new Preference(getContext());
        newPreference.setTitle("Preference " + mCounter);
        newPreference.setOrder(order);
        newPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
            @Override
            public boolean onPreferenceClick(Preference preference) {
                addPreference(preference);
                return false;
            }
        });
        mMyPreferenceCategory.addPreference(newPreference);
        mPreferenceList.add(newPreference);
        mCounter++;
    }
}