Search code examples
androidandroid-preferences

Add preferences to specific places in PreferenceScreen programmatically


I am populating parts of my preferences programmatically. This works fine. Unfortunately new preferences there has to be added, when the user changes some preferences (think of an 'add a new alarm'-preference). This works fine as well, when I use PreferenceCategories (because the new ones are added at the end of one such, so myPreferenceCategory.addPreference(newPreference) does the trick). But what can I do to programmatically add a Preference to any specific place (not just the end of usual categories/the prefScreen??


not so invisible category

I tried to use some kind of "invisible" PreferenceCategory, by setting android:layout="my_custom_invis_layout" with

<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"/>

Unfortunately those padding and margin does not seem to have an impact on the minimum space the empty category take (but do so with positive values, which is - of cause - of no help).


I tried as well to nullify the layout by

<PreferenceCategory
    android:layout="@null">

but this just enlarges the space the category takes to those the other preferences have.


Unfortunately SO did not help me on this so far. I would be very happy if anyone can point me to something like "add a preference A below preference B" or on how to make a category taking no space at all (as this would resolve my problem as well).


Solution

  • Ok, I've tried that other approach with Preferences#setOrder(int). (I left the previous answer there, cause for some use cases it might be the easier solution.) Does this one better suit your needs?

    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++;
        }
    }