Remover / ocultar uma preferência da tela

134

Eu tenho uma atividade que estende PreferenceActivity. Estou carregando preferências do arquivo xml. Mas, em alguns casos, preciso ocultar completamente uma das preferências da tela com base no estado do meu aplicativo. Existe um método setEnabled, mas não é exatamente o que eu quero. Eu quero remover completamente essa preferência da tela. É possível ?

Alex Volovoy
fonte

Respostas:

171

Sim, se você tiver uma referência ao Preferencepai e ao pai (a PreferenceCategoryou PreferenceScreen)

myPreferenceScreen.removePreference(myPreference);
David Hedlund
fonte
Ótimo! Obrigado! Funciona e faz todo sentido
Bostone
Eu poderia ter respondido minha própria pergunta por isso? stackoverflow.com/a/4704360/956975
marienke 23/02
2
Infelizmente, ele remove permanentemente a preferência. É possível apenas escondê-lo?
Dmitry
Também não funciona para mim. A preferência permanece!
Dmitry
@Dmitry Você pode acinzentá-lo comsetEnabled()
JakeD
212

Se você Preferenceestiver dentro de a PreferenceCategory, precisará fazer o seguinte:

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
fonte
5
Para ser justo, a resposta acima diz que você precisa dos pais PreferenceCategory.
Matt
49

No caso em que a preferência é um filho direto da tela de preferências, aqui está um código independente:

PreferenceScreen screen = getPreferenceScreen();
Preference pref = getPreferenceManager().findPreference("mypreference");
screen.removePreference(pref);
1 ''
fonte
4
Isso não funcionará se a preferência estiver localizada dentro da categoria. você precisa findPreferencepara a categoria e remova a preferência da categoria
MBH
1
@MBH: Obrigado por mencionar essa ressalva!
1 ''
9

Se você deseja algo que altere dinamicamente os prefs, por exemplo, em um SwitchPreference, achei a melhor maneira de colocar todas as minhas subopções em dois contêineres de categoria. Inicialmente, você terá tudo o que é mostrado e depois removerá os bits que não deseja. O mais inteligente, é que você apenas aciona a recriação quando algo muda e não precisa criar nada manualmente ou se preocupar em colocar as coisas de volta na ordem correta.

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

A única desvantagem que posso ver com isso é que há um flash quando a tela é recriada do zero.

James
fonte
O caso não funciona, pelo menos não em 22. Mas alterá-lo para uma preferência (mesmo que seja um agrupamento de preferências) funciona.
Rob
Rob, acabei de testar o código acima em um API22 AVD e está funcionando muito bem. Verifique se o conteúdo XML de sua preferência corresponde ao seu código. Para o exemplo acima, o SwitchPreference pode estar em qualquer lugar, mas você precisa que o PreferenceCategorys seja filho direto do PreferenceScreen.
James
Acabei de receber a categoria como preferência, sem elenco e a removi. Trabalhou.
Rob
8

No seu arquivo 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>

No seu 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
user3165739
fonte
8

Se você estiver usando PreferenceFragmentCompat, poderá definir a visibilidade em xml.

As preferências no seu xml serão convertidas para versões do AppCompat automaticamente. Você pode usar o atributo ' app: isPreferenceVisible ' no seu xml

preferências.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" />

...

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

A adição PreferenceFragmentCompatestá documentada em https://developer.android.com/guide/topics/ui/settings/#inflate_the_hierarchy

Exemplo:

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

No arquivo XML, você pode fazer uma preferência oculta deixando as tags de título e resumo em branco.

<EditTextPreference
    android:defaultValue="toddlerCam"
    android:key="save_photo_dir"
/>
Al Ro
fonte
Esta é a resposta perfeita para mim. Eu estive procurando por isso. Obrigado!
夏期劇場
2

Aqui está uma maneira genérica de fazer isso que funciona independentemente de a preferência estar sob um 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
fonte
0

Você pode fazer isso de duas maneiras:

1.Se você usa a biblioteca de suporte, pode criar um mapa da árvore de preferências e de seus pais e remover uma preferência usando o pai. Aqui está uma função para gerar esse 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. Se você usar a nova API de preferências do Android-x, poderá definir a visibilidade usando a função setVisible .
desenvolvedor android
fonte
De acordo com os documentos e a resposta de Tea setVisible() está disponível desde a versão 24.1.0 da biblioteca de suporte.
JJD 11/01/19
Você já olhou o que eu escrevi? Escrevi especificamente que isso é possível agora ... Além disso, a primeira solução ajuda na remoção, que é um pouco diferente de se esconder .. #
desenvolvedor android
Sim, eu li sua resposta. Eu estava me referindo ao seu segundo ponto. Ele lê como se o setVisibile()método estivesse disponível no android-x, que eu tentei esclarecer. Sem ofensa, por favor.
JJD
O Android-X é o único a substituir todas as bibliotecas de suporte. Não haverá novas versões da biblioteca de suporte como as conhecemos.
desenvolvedor android
Corrigir. Estou ciente disso . Ainda assim, as pessoas que estão presas a versões anteriores podem fazer uso do método.
JJD
0

Se você deseja avaliar, e com base nessa máscara, uma alternativa pode 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);
}

Tudo isso deve estar dentro

public static class PrefsFragment extends PreferenceFragment {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
Gustavo Eduardo Belduma
fonte
1
Desculpe, mas este é um site em inglês. Você pode responder em inglês?
Dave Schweisguth
Claro que minha intenção também era prover pessoas que não falam inglês
Gustavo Eduardo Belduma
3
@GustavoEduardoBelduma então você pode precisar de ler este meta.stackoverflow.com/a/297680/545026
Leo suporta Monica Cellio
0

Se você estiver fazendo o que acho que está tentando fazer (porque estou tentando fazê-lo agora), talvez seja melhor ativar / desativar a preferência. Como removê-lo, ele é retirado da tela de preferências e talvez você não possa adicioná-lo de volta para o local desejado, se criou a tela programaticamente.

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

embora isso possa ser preterido. Funciona para o caso de uso que estou passando agora.

RCB
fonte