42

I need to remove a PreferenceCategory programmatically. I could remove the individual preferences with the following code but I need to remove (disable) whole PreferenceCategory as well.

PreferenceScreen preferenceScreen = getPreferenceScreen();
EditTextPreference etp = (EditTextPreference) preferenceScreen.findPreference("pref22");
((PreferenceGroup) findPreference("prefcat")).removePreference(etp);

Edit: Here's the working code for a PreferenceCategory "prefcat" and a child preference "pref22":

PreferenceScreen preferenceScreen = getPreferenceScreen();
EditTextPreference etp = (EditTextPreference) preferenceScreen.findPreference("pref22");

PreferenceGroup preferenceGroup = (PreferenceGroup) findPreference("prefcat");
if (preferenceGroup != null) {
    preferenceGroup.removePreference(etp);
    preferenceScreen.removePreference(preferenceGroup);
}
RPB
  • 16,006
  • 16
  • 55
  • 79
Harald Wilhelm
  • 6,656
  • 11
  • 67
  • 85
  • What wasn't clear to me here was that you are asking about a PreferenceCategory, but your solution involves removing a preferenceGroup. I have the same situation...to clarify, my XML lists preferenceCategory, but I to get rid of that heading/group, I do exactly as you have done above programatically retrieving the reference to my preferenceCategory with a PreferenceGroup declaration. Hope that helps others. – taraloca Apr 05 '12 at 12:22
  • Oh, long time ago. If you look at the code you see that the category is casted to a PreferenceGroup. – Harald Wilhelm Apr 05 '12 at 12:40

4 Answers4

76

you can hide a category by getting reference to PreferenceScreen:

I your xml :

<PreferenceScreen 
xmlns:android="http://schemas.android.com/apk/res/android" 
android:key="@string/preferenceScreen">

//set all you values
//Preference, PreferenceCategory and/or CheckBoxPreference

</PreferenceScreen>

in you string.xml : don't forgot to set this new string

 <string name="preferenceScreen" translatable="false">preferenceScreen</string>

in you code:

preferenceScreen = (PreferenceScreen) findPreference(getResources().getString(R.string.preferenceScreen));

and then remove the category from your PreferenceScreen :

myCategory = (PreferenceCategory) findPreference(getResources().getString(R.string.my_category));
myPreferenceScreen.removePreference(myCategory);
OneWorld
  • 17,512
  • 21
  • 86
  • 136
douarbou
  • 2,283
  • 1
  • 21
  • 25
17

Provide a key for your PreferenceScreen and your PreferenceCategory in XML:

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    android:key="preferenceScreen" >

  <PreferenceCategory
     android:summary="@string/settings_billing_summary"
     android:title="Title"
     android:key="myPrefCat" >
      <Preference
      android:key="someKey"
      android:summary="Sum"
      android:title="Title" />
   </PreferenceCategory>

</PreferenceScreen>

From your class, you can now refer to your preferenceScreen and preferenceCategory and use the removePreference() method to remove the preference from the screen:

    PreferenceScreen preferenceScreen = (PreferenceScreen) findPreference("preferenceScreen");
    PreferenceCategory myPrefCat = (PreferenceCategory) findPreference("myPrefCat");
    preferenceScreen.removePreference(myPrefCat);

This answer is based on douarbou's answer which appears to be outdated, but is basically the same.

Community
  • 1
  • 1
Mdlc
  • 7,128
  • 12
  • 55
  • 98
  • This helped me enormously. But I used myPrefCat.setVisible(false/false) since I have a category to be shown only if I click a checkbox. Thanks a lot, you made my day! – Tomas F. Nov 19 '22 at 13:22
17

Don't load the PreferenceCategory in the first place.

If you are defining your preferences in Java, don't create the PreferenceCategory.

If you are defining your preferences in XML, use three XML files:

  1. One for stuff before this magic category
  2. One for the magic category
  3. One for stuff after this magic category

In situations where you want the category, load all three XML files. In situations where you do not want the category, load only the first and third XML files.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 1
    Thanks a lot. Will do so. Just for the records: There is no way to remove a PrefereneCategory, that has been loaded from XML, programmatically? – Harald Wilhelm Apr 09 '11 at 16:44
  • 1
    @hjw: I haven't tried it. I would think that `removePreference()` on the category would work, but I assumed you had tried that. Besides, if you don't need it, why load it in the first place? – CommonsWare Apr 09 '11 at 17:01
  • Yeah, you can use removePreference() – Ken Fehling Dec 17 '11 at 12:28
  • 1
    @CommonsWare, is there any other way to remove category at runtime other that making three files ? – Bipin Vayalu Nov 01 '13 at 21:24
  • @CommonsWare - what if I'm showing it at first, but then with some user input, I want to hide it (and maybe show it again later on)? – Mark Nov 14 '14 at 00:15
  • @Mark: Well, removing a `PreferenceCategory` is certainly possible (see below answer). Adding it back in later might be tricky. – CommonsWare Nov 14 '14 at 02:24
  • @CommonsWare - Yeah. Considering that maybe rolling my own ListView might be the simplest option right now. Argh! Android is so "half-baked" sometimes! :( – Mark Nov 14 '14 at 17:38
  • 1
    @CommonsWare - FYI - I made a sample project illustrating how to add and remove PreferenceCategories programatically. It's not too terrible and let's you leverage what Android provides, but keeps things still nice and flexible! https://github.com/markcerqueira/flexible_preferences – Mark Jan 26 '15 at 02:14
  • you didn't answer about programmatic way, so this is off-topic, I need programmatic way as author asked in the first place – user924 Sep 28 '18 at 07:00
  • just get the Preference by its id. Then hide the category with getParent().setVisible(false) – rouge Nov 28 '19 at 13:45
2

You can find the entire child-parent tree by traversing over all of the preferences and then check which is the parent of any preference you wish, even without using the id of the parent:

public static Map<Preference,PreferenceGroup> buildPreferenceParentTree(final PreferenceActivity activity)
    {
    final Map<Preference,PreferenceGroup> result=new HashMap<Preference,PreferenceGroup>();
    final Stack<PreferenceGroup> curParents=new Stack<PreferenceGroup>();
    curParents.add(activity.getPreferenceScreen());
    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;
    }

sample usage:

  final Map<Preference,PreferenceGroup> preferenceParentTree=buildPreferenceParentTree(SettingsActivity.this);
  final PreferenceGroup preferenceGroup=preferenceParentTree.get(preferenceToRemove);
  preferenceGroup.removePreference(preferenceToRemove);

EDIT: seems there is a new API for this :

https://developer.android.com/reference/androidx/preference/Preference#setVisible(boolean)

I'm not sure if currently it's available or not, though.

android developer
  • 114,585
  • 152
  • 739
  • 1,270