Remove/hide a preference from the screen

Viewed 79051

I have an activity which extends PreferenceActivity. I'm loading preferences from the xml file. But in some cases i need completely hide one of the preferences from the screen based on my app state. There is a setEnabled method, but it's not exactly what i want. I want to remove that preference from the screen completely. Is it possible ?

15 Answers

Yes, if you have a reference to both the Preference, and its parent (a PreferenceCategory, or PreferenceScreen)

myPreferenceScreen.removePreference(myPreference);

If you are using PreferenceFragmentCompat you can set the visiblity in xml.

The preferences in your xml will be converted to AppCompat versions automatically. You can then use the 'app:isPreferenceVisible' attribute in your xml

preferences.xml

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <CheckBoxPreference
        android:defaultValue="false"
        android:key="show.navigation"
        android:title="Show navigation"
        app:isPreferenceVisible="false" />

...

The attribute is documented at https://developer.android.com/guide/topics/ui/settings/components-and-attributes

Adding PreferenceFragmentCompat is documented at https://developer.android.com/guide/topics/ui/settings/#inflate_the_hierarchy

Example:

public class MySettingsActivity extends AppCompatActivity {

    public static class MySettingsFragment extends PreferenceFragmentCompat {
        @Override
        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
            setPreferencesFromResource(R.xml.preferences, rootKey);
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getSupportFragmentManager()
                .beginTransaction()
                .replace(R.id.settings_container, new MySettingsFragment())
                .commit();
    }
} 

There is a simple workaround:

//In your Activity code after finding the preference to hide:
    if(pref!=null) {
        pref.setEnabled(false);
        pref.setSelectable(false);
        //Following line will replace the layout of your preference by an empty one
        pref.setLayoutResource(R.layout.preference_hidden);
    }

And create a preference_hidden layout:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="0dp"/>

Wherever is your Preference to hide (in a PreferenceGroup or at root) it will work!

You can do this in 2 ways:

1.If you use support library, you can build a map of the tree of preferences and their parents, and then remove a preference by using its parent. Here's a function to generate such a map:

public static Map<Preference, PreferenceGroup> buildPreferenceParentTree(@NonNull final PreferenceScreen preferenceScreen) {
    final Map<Preference, PreferenceGroup> result = new HashMap<>();
    final Stack<PreferenceGroup> curParents = new Stack<>();
    curParents.add(preferenceScreen);
    while (!curParents.isEmpty()) {
        final PreferenceGroup parent = curParents.pop();
        final int childCount = parent.getPreferenceCount();
        for (int i = 0; i < childCount; ++i) {
            final Preference child = parent.getPreference(i);
            result.put(child, parent);
            if (child instanceof PreferenceGroup)
                curParents.push((PreferenceGroup) child);
        }
    }
    return result;
}
  1. If you use the new android-x preference API, you can just set the visibility, by using setVisible function on it.

If you're doing what I think you're trying to do (because I'm trying to do it now) it might be better to enable/disable the preference. Because removing it takes it out of the preference screen and you might not be able to add it back where you want it if you made the screen programmatically.

pref.setEnabled(false); pref.setEnabled(true);

although this might be deprecated. It works for the use case that I'm going through right now.

If all you need is not to show the preference i.e. hide the preference then do the following

findPreference<Preference>("keyName").isVisible = false

code is in kotlin

Note : This is AndroidX preferences (don't know if same with hold with earlier Preference)

Related