Dominikus K.
Dominikus K.

Reputation: 283

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).

Upvotes: 5

Views: 2488

Answers (3)

Slion
Slion

Reputation: 3068

You can sort preferences alphabetically by title. To do so you need to set isOrderingAsAdded to false for the PreferenceGroup your are using, category or screen. Thus when you add a new preference it just takes its place.

Upvotes: 0

kazume
kazume

Reputation: 1373

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

Upvotes: 3

kazume
kazume

Reputation: 1373

I see this question is quite old, but since I was facing a similar problem and managed to solved it, I figured there would be no harm done by posting anyway. The way I solved this is by adding the Preference (in my case a category that needed to be added in a particular spot amongst the other categories) in xml from the start, removing it programmatically if not yet needed. When putting it back (programmatically) afterwards, it appears at the same position it was before removing it. Haven't tried your particular case (with single Preferences needing to go in a particular spot within a category), but I bet it works the same way.

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

Upvotes: 5

Related Questions