Eliminar / ocultar una preferencia de la pantalla

134

Tengo una actividad que extiende PreferenceActivity. Estoy cargando preferencias del archivo xml. Pero en algunos casos necesito ocultar completamente una de las preferencias de la pantalla en función del estado de mi aplicación. Hay un método setEnabled, pero no es exactamente lo que quiero. Quiero eliminar esa preferencia de la pantalla por completo. Es posible ?

Alex Volovoy
fuente

Respuestas:

171

Sí, si tiene una referencia a ambos Preference, y su padre (a PreferenceCategory, o PreferenceScreen)

myPreferenceScreen.removePreference(myPreference);
David Hedlund
fuente
¡Excelente! ¡Gracias! Funciona y tiene mucho sentido
Bostone
¿Podría haber respondido mi propia pregunta a través de esto? stackoverflow.com/a/4704360/956975
marienke
2
Desafortunadamente, elimina permanentemente la preferencia. ¿Es posible solo ocultarlo?
Dmitry
Tampoco me funciona. La preferencia permanece!
Dmitry el
@Dmitry Puedes atenuarlosetEnabled()
JakeD
212

Si Preferenceestá dentro de a PreferenceCategory, debe hacer esto:

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
fuente
55
Para ser justos, la respuesta anterior dice que necesitas a los padres PreferenceCategory.
mate
49

En el caso de que la Preferencia sea un elemento secundario directo de la pantalla de preferencias, aquí hay un código independiente:

PreferenceScreen screen = getPreferenceScreen();
Preference pref = getPreferenceManager().findPreference("mypreference");
screen.removePreference(pref);
1 ''
fuente
44
Esto no funcionará si la preferencia se encuentra dentro de la categoría. debe hacerlo findPreferencepara la categoría y eliminar la preferencia de la categoría
MBH
1
@MBH: ¡Gracias por mencionar esa advertencia!
1 ''
9

Si desea algo que cambie dinámicamente las preferencias, por ejemplo, en una SwitchPreference, he encontrado que la mejor manera es poner todas mis opciones secundarias en contenedores de dos categorías. Inicialmente tendrá todo lo que se muestra, luego simplemente elimine los bits que no desea. Lo más inteligente es que simplemente activa la recreación cuando algo cambia y luego no tiene que crear nada manualmente ni preocuparse por volver a poner las cosas en el orden correcto.

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

El único inconveniente que puedo ver con esto es que hay un destello ya que la pantalla se recrea desde cero.

James
fuente
El caso no funciona, al menos no en 22. Pero cambiarlo a Preferencia (aunque sea una agrupación de preferencias) sí funciona.
Rob
Rob, acabo de probar el código anterior en un AVD API22 y está funcionando bien. Asegúrese de que su contenido XML preferido coincida con su código. Para el ejemplo anterior, la SwitchPreference puede estar en cualquier lugar, pero necesita PreferenceCategorys para ser hijos directos de PreferenceScreen.
James
Acabo de recibir la Categoría como Preferencia, sin yeso, y la eliminé. Trabajó.
Rob el
8

En su archivo 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>

En su código:

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
usuario3165739
fuente
8

Si está utilizando PreferenceFragmentCompat , puede establecer la visibilidad en xml.

Las preferencias en su xml se convertirán a versiones de AppCompat automáticamente. Luego puede usar el atributo ' app: isPreferenceVisible ' en su xml

preferencias.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" />

...

El atributo está documentado en https://developer.android.com/guide/topics/ui/settings/components-and-attributes

La adición PreferenceFragmentCompatestá documentada en https://developer.android.com/guide/topics/ui/settings/#inflate_the_hierarchy

Ejemplo:

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
fuente
3

En el archivo XML puede hacer una preferencia oculta dejando vacías las etiquetas de título y resumen.

<EditTextPreference
    android:defaultValue="toddlerCam"
    android:key="save_photo_dir"
/>
Al Ro
fuente
Esta es la respuesta perfecta para mí. He estado buscando esto. ¡Gracias!
夏 期 劇場
2

Aquí hay una forma genérica de hacer esto que funciona independientemente de si la preferencia está bajo PreferenceCategoryo 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
fuente
0

Puedes hacer esto de 2 maneras:

1.Si usa la biblioteca de soporte, puede construir un mapa del árbol de preferencias y sus padres, y luego eliminar una preferencia usando su padre. Aquí hay una función para generar dicho mapa:

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 usa la nueva API de preferencia de Android-x, puede establecer la visibilidad, utilizando la función setVisible en ella.
desarrollador de Android
fuente
De acuerdo con los documentos y la respuesta de Tea setVisible() está disponible desde la versión 24.1.0 de la biblioteca de Soporte.
JJD
¿Has mirado lo que escribí? Escribí específicamente que ahora es posible ... Además, la primera solución ayuda con la eliminación, que es un poco diferente a la ocultación ...
desarrollador de Android
Sí, leí tu respuesta. Me refería a tu segundo punto. Se lee como si el setVisibile()método estuviera disponible en android-x, que intenté aclarar. Sin ofender por favor.
JJD
Android-X es el que reemplaza todas las bibliotecas de soporte. No habrá nuevas versiones de la biblioteca de soporte tal como las conocemos.
Desarrollador de Android el
Correcto. Soy consciente de esto . Aún así, las personas que están atrapadas con versiones anteriores pueden hacer uso del método.
JJD
0

Si desea evaluar, y en base a esa máscara, una alternativa puede ser

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

Todo esto debe estar dentro

public static class PrefsFragment extends PreferenceFragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
Gustavo Eduardo Belduma
fuente
1
Lo siento, pero este es un sitio en inglés. ¿Puedes responder en inglés?
Dave Schweisguth
Por supuesto, mi intención también era proporcionar a las personas que no hablan inglés
Gustavo Eduardo Belduma
3
@GustavoEduardoBelduma, entonces es posible que deba leer este meta.stackoverflow.com/a/297680/545026
Leo apoya a Monica Cellio el
0

Si está haciendo lo que creo que está tratando de hacer (porque estoy tratando de hacerlo ahora), podría ser mejor habilitar / deshabilitar la preferencia. Debido a que eliminarlo lo saca de la pantalla de preferencias y es posible que no pueda volver a agregarlo donde lo desea si creó la pantalla mediante programación.

pref.setEnabled (falso); pref.setEnabled (verdadero);

aunque esto podría estar en desuso. Funciona para el caso de uso que estoy pasando en este momento.

RCB
fuente