How to show and hide preferences on Android dynamically?

后端 未结 6 776
隐瞒了意图╮
隐瞒了意图╮ 2020-12-23 17:46

Is there a way to dynamically show and hide preferences? In my case, I have a checkbox preference that would disable or enable one of 2 preference groups (\"with-\" and \"w

相关标签:
6条回答
  • 2020-12-23 18:17

    Not exactly hiding/showing but if you only want disabling/enabling preference depending on another preference you can specify android:dependency="preferenceKey" or Preference.setDependency(String)

    Example from developer.android.com:

    <?xml version="1.0" encoding="utf-8"?>
    <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
        <CheckBoxPreference
            android:key="pref_sync"
            android:title="@string/pref_sync"
            android:summary="@string/pref_sync_summ"
            android:defaultValue="true" />
        <ListPreference
            android:dependency="pref_sync"
            android:key="pref_syncConnectionType"
            android:title="@string/pref_syncConnectionType"
            android:dialogTitle="@string/pref_syncConnectionType"
            android:entries="@array/pref_syncConnectionTypes_entries"
            android:entryValues="@array/pref_syncConnectionTypes_values"
            android:defaultValue="@string/pref_syncConnectionTypes_default" />
    </PreferenceScreen>
    
    0 讨论(0)
  • 2020-12-23 18:20

    From a PreferenceActivity call

    Preference somePreference = findPreference(SOME_PREFERENCE_KEY);
    PreferenceScreen preferenceScreen = getPreferenceScreen();
    preferenceScreen.removePreference(somePreference);
    

    you can later call:

    preferenceScreen.addPreference(somePreference);
    

    The only a little bit tricky part is getting the order correct when adding back in. Look at PreferenceScreen documentation, particularly it's base class, PreferenceGroup for details.

    Note: The above will only work for immediate children of a PreferenceScreen. If there is a PreferenceCategory in between, you need to remove the preference from its parent PreferenceCategory, not the PreferenceScreen. First to ensure the PreferenceCategory has an android:key attribute set in the XML file. Then:

    Preference somePreference = findPreference(SOME_PREFERENCE_KEY);
    PreferenceCategory preferenceCategory = (PreferenceCategory) findPreference(SOME_PREFERENCE_CATEGORY_KEY);
    preferenceCategory.removePreference(somePreference);
    

    and:

    preferenceCategory.addPreference(somePreference);
    
    0 讨论(0)
  • 2020-12-23 18:21

    If you want to implement the hiding of the preference completely in the Preference, here is one example. Does not allow to make it visible again, though.

    public class RemovablePreference extends Preference {
    
    @Override
    protected void onBindView(View view) {
        super.onBindView(view);
    
        updateVisibility(); // possibly a better place available?
    }
    
    private void updateVisibility() {
        Context context = getContext(); // should be a PreferenceActivity
        if (context instanceof PreferenceActivity) {
            updateVisibility((PreferenceActivity)context);
        }
    }
    
    private void updateVisibility(PreferenceActivity activity) {
        updateVisibility(getPreferenceScreen(activity));
    }
    
    private PreferenceScreen getPreferenceScreen(PreferenceActivity activity) {
    
        if (activity.getPreferenceScreen() != null) {
            return activity.getPreferenceScreen(); // for old implementations
        }
    
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            Fragment fragment = activity.getFragmentManager().findFragmentById(android.R.id.content);
            if (fragment instanceof PreferenceFragment) {
                return ((PreferenceFragment) fragment).getPreferenceScreen();
            }
        }
        return null;
    }
    
    private void updateVisibility(PreferenceScreen screen) {
        if (!isVisible() && screen != null) {
            hidePreference(screen, this);
        }
    }
    
    private boolean hidePreference(PreferenceGroup prefGroup, Preference removedPreference) {
        boolean removed = false;
    
        if (prefGroup.removePreference(removedPreference)) {
            removed = true;
        }
    
        for (int i = 0; i < prefGroup.getPreferenceCount(); i++) {
            Preference preference = prefGroup.getPreference(i);
            if (preference instanceof PreferenceGroup) {
                PreferenceGroup prefGroup2 = (PreferenceGroup)preference;
                if (hidePreference(prefGroup2, this)) {
                    // The whole group is now empty -> remove also the group
                    if (prefGroup2.getPreferenceCount() == 0) {
                        removed = true;
                        prefGroup.removePreference(prefGroup2);
                    }
                }
            }
        }
    
        return removed;
    }
    
    protected boolean isVisible() {
        return true; // override
    }
    
    0 讨论(0)
  • 2020-12-23 18:34

    I needed something similar: toggling a switch to hide or show two extra preferences. Check out the sample app from Android-Support-Preference-V7-Fix which bring some new preference types and fixes some issues from the official library. There's an example there to toggle a checkbox to show or hide a preference category.

    In the fragment that extends PreferenceFragmentCompatDividers, you could use something like:

    findPreference("pref_show_extra_stuff").setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                findPreference("pref_extra_stuff_01").setVisible((Boolean) newValue);
                findPreference("pref_extra_stuff_02").setVisible((Boolean) newValue);
                return true;
            }
        });
    

    pref_extra_stuff_01 and pref_extra_stuff_02 are the two preferences that are hidden when pref_show_extra_stuff is toggled.

    0 讨论(0)
  • 2020-12-23 18:40

    I recommend using V7 preference, it has setVisible() method. But I have not tried it yet.

    0 讨论(0)
  • 2020-12-23 18:42

    For hiding preferences dynamically, I created an if-condition upon whose value I decide whether I want the pref to show or not. To do the actual hiding, I have been using:

        findPreference(getString(R.string.pref_key)).setLayoutResource(R.layout.hidden);
    

    The tricky part is to make it visible again. There is no direct way to do it except to recreate the layout. If the value of the if-condition is false, which means the pref should be visible, then the code to hide the pref will never be executed, thus resulting in a visible pref. Here is how to recreate the layout (in my case, I am extending a PreferencesListFragment):

        getActivity().recreate();
    

    I hope that was helpful.

    0 讨论(0)
提交回复
热议问题