Supprimer / masquer une préférence de l'écran

134

J'ai une activité qui étend PreferenceActivity. Je charge les préférences à partir du fichier xml. Mais dans certains cas, je dois masquer complètement l'une des préférences de l'écran en fonction de l'état de mon application. Il existe une méthode setEnabled, mais ce n'est pas exactement ce que je veux. Je souhaite supprimer complètement cette préférence de l'écran. C'est possible ?

Alex Volovoy
la source

Réponses:

171

Oui, si vous avez une référence à la fois au Preference, et à son parent (a PreferenceCategory, ou PreferenceScreen)

myPreferenceScreen.removePreference(myPreference);
David Hedlund
la source
Génial! Merci! Fonctionne et prend tout son sens
Bostone
J'aurais pu répondre à ma propre question à travers cela? stackoverflow.com/a/4704360/956975
marienke
2
Malheureusement, cela supprime définitivement la préférence. Est-il possible de le cacher?
Dmitry
Cela ne fonctionne pas non plus pour moi. La préférence demeure!
Dmitry
@Dmitry Vous pouvez simplement le setEnabled()
griser
212

Si vous êtes Preferencedans un PreferenceCategory, vous devez faire ceci:

XML:

<PreferenceCategory
    android:key="category_foo"
    android:title="foo">

    <CheckBoxPreference
        android:key="checkPref" />

Java:

CheckBoxPreference mCheckBoxPref = (CheckBoxPreference) findPreference("checkPref");
PreferenceCategory mCategory = (PreferenceCategory) findPreference("category_foo");
mCategory.removePreference(mCheckBoxPref);
Kavi
la source
5
Pour être juste, la réponse ci-dessus indique que vous avez besoin du parent PreferenceCategory.
mat
49

Dans le cas où la préférence est un enfant direct de l'écran des préférences, voici un code autonome:

PreferenceScreen screen = getPreferenceScreen();
Preference pref = getPreferenceManager().findPreference("mypreference");
screen.removePreference(pref);
1''
la source
4
Cela ne fonctionnera pas si la préférence est située dans la catégorie. vous devez findPreferencepour la catégorie et supprimer la préférence de la catégorie
MBH
1
@MBH: Merci d'avoir mentionné cette mise en garde!
1 '' du
9

Si vous voulez quelque chose qui changera dynamiquement les préférences, par exemple sur un SwitchPreference, j'ai trouvé que le meilleur moyen est de mettre toutes mes sous-options dans deux conteneurs de catégorie. Au départ, tout sera affiché, puis supprimez simplement les bits dont vous ne voulez pas. Le plus intelligent, c'est que vous déclenchez simplement la recréation lorsque quelque chose change et que vous n'avez pas à créer manuellement quoi que ce soit ou à vous soucier de remettre les choses dans le bon ordre.

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  addPreferencesFromResource(R.xml.preferences);
  PreferenceCategory prefCatOne= (PreferenceCategory)findPreference("prefCatOne");
  PreferenceCategory prefCatTwo= (PreferenceCategory)findPreference("prefCatTwo");
  SwitchPreference mySwitchPref= (SwitchPreference)findPreference("mySwitchPref");
  PreferenceScreen screen = getPreferenceScreen();
  if (mySwitchPref.isChecked()) {
    screen.removePreference(prefCatOne);
  } else {
    screen.removePreference(prefCatTwo);
  }
}

public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
    if (key.equals("mySwitchPref")) {
        this.recreate();
    }
}

Le seul inconvénient que je peux voir avec cela, c'est qu'il y a un flash car l'écran est recréé à partir de zéro.

James
la source
Le cas ne fonctionne pas, du moins pas dans 22. Mais le changer en préférence (même s'il s'agit d'un regroupement de préférences) fonctionne.
Rob
Rob, je viens de tester le code ci-dessus dans un AVD API22 et cela fonctionne très bien. Assurez-vous que le contenu XML de vos préférences correspond à votre code. Pour l'exemple ci-dessus, SwitchPreference peut être n'importe où, mais vous avez besoin que les PreferenceCategorys soient des enfants directs de PreferenceScreen.
James
Je viens de recevoir la catégorie en tant que préférence, pas de distribution, et je l'ai supprimée. Travaillé.
Rob
8

Dans votre fichier XML:

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

    <PreferenceCategory
        android:key="personalisation"
        android:title="your title here">

        <ThemedPreference
            android:key="animation" />

</PreferenceScreen>

Dans votre code:

PreferenceScreen pPreferenceScreen = (PreferenceScreen) findPreference("preferenceScreen");

PreferenceCategory pCategory = (PreferenceCategory) findPreference("personalisation");
ThemedPreference pThemePref = (ThemedPreference) findPreference("animation");

pPreferenceScreen.removePreference(pCategory); //remove category
pCategory.removePreference(pThemePref);   // remove preference
user3165739
la source
8

Si vous utilisez PreferenceFragmentCompat, vous pouvez définir la visibilité en xml.

Les préférences de votre xml seront automatiquement converties en versions AppCompat. Vous pouvez ensuite utiliser l' attribut ' app: isPreferenceVisible ' dans votre 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" />

...

L'attribut est documenté sur https://developer.android.com/guide/topics/ui/settings/components-and-attributes

L'ajout PreferenceFragmentCompatest documenté sur https://developer.android.com/guide/topics/ui/settings/#inflate_the_hierarchy

Exemple:

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();
    }
} 
Aaronvargas
la source
3

Dans le fichier XML, vous pouvez créer une préférence masquée en laissant les balises de titre et de résumé vides.

<EditTextPreference
    android:defaultValue="toddlerCam"
    android:key="save_photo_dir"
/>
Al Ro
la source
C'est la réponse parfaite pour moi. Je cherchais ça. Je vous remercie!
夏 期 劇場
2

Voici une façon générique de faire cela qui fonctionne indépendamment du fait que la préférence soit sous PreferenceCategoryou PreferenceScreen.

private void removePreference(Preference preference) {
    PreferenceGroup parent = getParent(getPreferenceScreen(), preference);
    if (parent == null)
        throw new RuntimeException("Couldn't find preference");

    parent.removePreference(preference);
}

private PreferenceGroup getParent(PreferenceGroup groupToSearchIn, Preference preference) {
    for (int i = 0; i < groupToSearchIn.getPreferenceCount(); ++i) {
        Preference child = groupToSearchIn.getPreference(i);

        if (child == preference)
            return groupToSearchIn;

        if (child instanceof PreferenceGroup) {
            PreferenceGroup childGroup = (PreferenceGroup)child;
            PreferenceGroup result = getParent(childGroup, preference);
            if (result != null)
                return result;
        }
    }

    return null;
}
Sam
la source
0

Vous pouvez le faire de 2 manières:

1.Si vous utilisez la bibliothèque de support, vous pouvez créer une carte de l'arborescence des préférences et de leurs parents, puis supprimer une préférence en utilisant son parent. Voici une fonction pour générer une telle carte:

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. Si vous utilisez la nouvelle API de préférences android-x, vous pouvez simplement définir la visibilité en utilisant la fonction setVisible .
développeur android
la source
Selon la documentation et la réponse de Tea setVisible() est disponible depuis la version 24.1.0 de la bibliothèque de support.
JJD
Avez-vous regardé ce que j'ai écrit? J'ai spécifiquement écrit que c'est possible maintenant ... De plus, la première solution aide à la suppression, ce qui est un peu différent de la dissimulation.
développeur android
Oui, j'ai lu votre réponse. Je faisais référence à votre deuxième point. Il se lit comme si la setVisibile()méthode était disponible à partir de android-x que j'ai essayé de clarifier. Aucune offense s'il vous plaît.
JJD
Android-X est celui qui remplace toutes les bibliothèques de support. Il n'y aura pas de nouvelles versions de la bibliothèque de support telles que nous les connaissons.
développeur android
Correct. J'en suis conscient . Pourtant, les personnes qui sont coincées avec les anciennes versions peuvent utiliser la méthode.
JJD
0

Si vous souhaitez évaluer, et sur la base de ce masque, une alternative peut être

SwitchPreference autenticacionUsuario = 
    (SwitchPreference) findPreference("key_autenticacion_usuario");

final EditTextPreference Username = 
    (EditTextPreference) findPreference("key_username_mqtt");
final EditTextPreference Password = 
    (EditTextPreference) findPreference("key_password_mqtt");

if (!autenticacionUsuario.isChecked()) {
    PreferenceCategory preferenceCategory = 
        (PreferenceCategory) findPreference("category_mqtt");
    preferenceCategory.removePreference(Username);
    preferenceCategory.removePreference(Password);
}

Tout cela doit être à l'intérieur

public static class PrefsFragment extends PreferenceFragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
Gustavo Eduardo Belduma
la source
1
Désolé, mais c'est un site en anglais. Pouvez-vous répondre en anglais?
Dave Schweisguth
Bien sûr, mon intention était aussi de pourvoir aux personnes qui ne parlent pas anglais
Gustavo Eduardo Belduma
3
@GustavoEduardoBelduma alors vous devrez peut-être lire ce meta.stackoverflow.com/a/297680/545026
Leo soutient Monica Cellio le
0

Si vous faites ce que je pense que vous essayez de faire (parce que j'essaye de le faire maintenant), il vaudrait peut-être mieux activer / désactiver la préférence. Parce que sa suppression le retire de l'écran des préférences et vous ne pourrez peut-être pas le rajouter où vous le souhaitez si vous avez créé l'écran par programme.

pref.setEnabled (false); pref.setEnabled (vrai);

bien que cela puisse être obsolète. Cela fonctionne pour le cas d'utilisation que je traverse actuellement.

RCB
la source