Preferências da lista do Android: tem o resumo como valor selecionado?

112

Eu tenho uma atividade de preferência que usa uma lista de preferências conforme definido por meu arquivo XML. Como eu definiria o resumo da atividade da lista com o valor selecionado?

Obrigado!

Fran Fitzpatrick
fonte

Respostas:

411

A maneira mais simples de fazer isso é deixar que o Android faça isso por você. Supondo que você quer o resumo para corresponder ao valor selecionado, você pode simplesmente definir o resumo do ListPreferenceque"%s" usando XML ou o setSummarymétodo em Java. Por exemplo:

<ListPreference
    android:key="pref_list"
    android:title="A list of preferences"
    android:summary="%s"
    android:entries="@array/pref_list_entries"
    android:entryValues="@array/pref_list_entries_values"
    android:defaultValue="0" />

O Android substituirá %spelo valor da string atual da preferência, conforme exibido pelo ListPreferenceseletor do. O resumo da lista também será definido corretamente quando você entrar na atividade - você não precisa escrever nenhum código especial para configurá-la inicialmente.

Isso também funciona com o AndroidX ListPreference.

Passei muito tempo demais mucking com SharedPreferencesouvintes antes que eu descobri isso.

George Hilliard
fonte
1
Eu sei! Adoro essas soluções elegantes. Tão simples, mas difícil de encontrar;)
sgably
7
Tive que combinar isso com a atualização manual ... porque o resumo não é atualizado quando o valor é alterado ...
Renetik
4
Excelente resposta. Acredite ou não, mas na verdade está documentado: developer.android.com/reference/android/preference/…
Lior
1
Você pode confirmar que precisa de API> = 11 para "%s"? Em meus testes, "%s"não funciona com o Gingerbread e versões anteriores.
andreas1724
1
@BaptisteCandellier, obrigado pelo aviso. Se algo existir, a equipe do Android irá descontinuá-lo. Eu adicionei um link para androidx.
George Hilliard
29

Você pode usar OnPreferenceChangeListenerpara alterar dinamicamente o resumo. O problema é que ele obtém o valor selecionado (de android:entryValues), não a legenda ( android:entries). Usei o código a seguir toString(), mas a solução adequada é encontrar a legenda para o valor. De qualquer forma, a ideia funciona:

public class Preferences extends PreferenceActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.your_prefs);

        ListPreference listPreference = (ListPreference) findPreference("preference_key");
        if(listPreference.getValue()==null) {
            // to ensure we don't get a null value
            // set first value by default
            listPreference.setValueIndex(0);
        }
        listPreference.setSummary(listPreference.getValue().toString());
        listPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                preference.setSummary(newValue.toString());
                return true;
            }
        });
    }
}
Axel
fonte
18

Eu também queria conseguir algo semelhante, mas o problema com https://stackoverflow.com/a/8155029/592025 é que ele mostra o valor da minha preferência (como 1, 2 3 etc.). Desejo mostrar a entrada (string legível por humanos) correspondente ao valor selecionado.

Então mudei dessa forma e funciona da maneira que preciso.

listPreference.setSummary(servicePreference.getEntry().toString());
listPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            // Set the value as the new value
            listPreference.setValue(newValue.toString());
            // Get the entry which corresponds to the current value and set as summary
            preference.setSummary(listPreference.getEntry());
            return false;
        }
    });

O truque é usar em getEntry()vez de getValue()e depois que o valor for alterado, definir o valor explicitamente e ler a entrada.

Midhunhk
fonte
8

Acho que o que você está procurando é muito simples do que você pode imaginar, adicione a seguinte linha de código ao seu Preferenceitem:

android:summary="%1$s"

Portanto, será mais ou menos assim:

<ListPreference
            android:key="@string/pref_temp_key"
            android:title="@string/pref_temp_title"
            android:dialogTitle="@string/pref_temp_dialog_title"
            android:entries="@array/pref_tempUnit_entries"
            android:entryValues="@array/pref_tempUnit_entries"
            android:summary="%1$s"
            android:defaultValue="@string/pref_temp_default_value" />
42Geek
fonte
4

Primeiro, obtenha uma referência a ListPreference em seu onCreate. Você pode usar findPreference (). Por exemplo:

ListPreference pref = (ListPreference) findPreference("thePreferencesKey");

Então, quando você carregar a Activity pela primeira vez e sempre que o valor de preferências for alterado, use qualquer método que você deseja obter o valor de ListPreference e defina o resumo com:

pref.setSummary(theNewString);
CottonBallPaws
fonte
2

Este é o código que estou usando, não chama setValue manualmente, pois acredito que isso já seja feito em um estágio posterior.

Aqui está um exemplo:

@Override
public boolean onPreferenceChange(Preference preference, Object value)
{
    String textValue = value.toString();

    ListPreference listPreference = (ListPreference) preference;
    int index = listPreference.findIndexOfValue(textValue);

    CharSequence[] entries = listPreference.getEntries();

    preference.setSummary(
                index >= 0
                        ? entries[index]
                        : null);

    return true;
}
Moberg
fonte
0

Isso é exatamente o que eu fiz e funciona muito bem. No onSharedPreferenceChangeListener , apenas verifico a chave do que está sendo alterado e, em ListPreferences, converto de volta para Human legable (entrada em vez de entryValue) com as instruções if. Bem simples.

public class MyPreferences extends PreferenceFragment implements OnSharedPreferenceChangeListener{

public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.preferences);
    context = getActivity();

    if (context == null){
        Log.e("error","context is null");
    }

    prefs = PreferenceManager.getDefaultSharedPreferences(context);
    myFrequencyList = (Preference)  findPreference("frequency_key");
    prefs.registerOnSharedPreferenceChangeListener(this);

}


@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
        String key) {

        if(key.equals("frequency_key")){
                String freq = sharedPreferences.getString("frequency_key", "8k Hz");
                if(freq.equals("8000")){
                    freq = "8k Hz";
                }
                else if(freq.equals("16000")){
                    freq = "16k Hz";
                }
                else if(freq.equals("22050")){
                    freq = "22.05k Hz";
                }
                else if(freq.equals("44100")){
                    freq = "44.1k Hz";
                }
                else if(freq.equals("48000")){
                    freq = "48k Hz";
                }
                else{
                    freq = "8k Hz";
                }
                myFrequencyList.setSummary(freq);
        }

layout xml

 <ListPreference android:id="@+id/frequency_list"
        android:key="frequency_key"
        android:summary="8000"
        android:title="Sample Rate"
        android:defaultValue="8000"
        android:dialogTitle="Larger sample rates create better sound quality but larger file sizes."
        android:entries="@array/freq_titles"
        android:entryValues="@array/freq_values"
        />

array xml

<?xml version="1.0" encoding="utf-8"?>

<string-array name="freq_titles">
    <item>48k Hz</item>
    <item>44.1k Hz</item>
    <item>22.05k Hz</item>
    <item>16k Hz</item>
    <item>8k Hz</item>
</string-array>

<string-array name="freq_values">
    <item>48000</item>
    <item>44100</item>
    <item>22050</item>
    <item>16000</item>
    <item>8000</item>
</string-array>

Jordan Hochstetler
fonte
1
O ideal é que você leia o resumo dinamicamente para que não precise acompanhá-lo em dois lugares.
George Hilliard
0

Aqui está uma versão expandida da resposta de midhunhk que também aborda a útil string "android: summary"

        // Retrieve & populate flash modes
        List<String> flashmodes = params.getSupportedFlashModes();
        if (flashmodes != null) {
            final ListPreference lp = (ListPreference) findPreference("flash_list");
            final String lp_basesummary = "Set the Flash mode. The default is 'auto'";

            lp.setEntries(flashmodes.toArray(new CharSequence[flashmodes.size()]));
            lp.setEntryValues(flashmodes.toArray(new CharSequence[flashmodes.size()]));
            // If there's only one option, make it the default
            if (flashmodes.size() == 1)
                lp.setValueIndex(0);

            lp.setSummary(lp_basesummary + " [" + lp.getEntry() + "]");

            lp.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

                @Override
                public boolean onPreferenceChange(Preference preference, Object newValue) {
                    // Set the value as the new value
                    lp.setValue(newValue.toString());
                    // Get the entry which corresponds to the current value
                    // and set as summary
                    preference.setSummary(lp_basesummary + " [" + lp.getEntry() + "]");
                    return false;
                }
            });
        } else {
            // Remove the preference
            ((PreferenceGroup) findPreference("camera_preference")).removePreference(findPreference("flash_list"));
        }

        // Retrieve & populate focus modes
        List<String> focusmodes = params.getSupportedFocusModes();
        if (focusmodes != null) {
            final ListPreference lp = (ListPreference) findPreference("focus_mode_list");
            final String lp_basesummary = "Set the Focus mode. The default is 'auto'";
...

E, só para ficar claro, android: summary foi removido do xml relacionado.

RudyF
fonte
0

E aqui está uma maneira de lidar com a atualização do resumo das preferências de toque após a seleção do usuário.

    final SharedPreferences preference = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

    final RingtonePreference rp_shuttle = (RingtonePreference) findPreference("shuttle_tone");
    rp_shuttle.setSummary(RingtoneManager
            .getRingtone(getApplicationContext(), Uri.parse(preference.getString("shuttle_tone", "DEFAULT_SOUND")))
            .getTitle(this));

    rp_shuttle.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

        public boolean onPreferenceChange(Preference mypreference, Object newValue) {
            rp_shuttle.setSummary(RingtoneManager.getRingtone(getApplicationContext(), Uri.parse(newValue + ""))
                    .getTitle(getApplicationContext()));

            return true;
        }
    })
RudyF
fonte
0

Você tem um método bindPreferenceSummaryToValue em seu PreferenceActivity,

você pode adicionar facilmente o resumo à lista fazendo o seguinte:

private static void bindPreferenceSummaryToValue(Preference preference) {
    preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);

    sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
            PreferenceManager
                    .getDefaultSharedPreferences(preference.getContext())
                    .getString(preference.getKey(), ""));
}

No método OnCreate, você chama a função de ligação assim:

bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_OF_THE_LIST)));

Você pode adicionar outros resumos facilmente da mesma maneira:

bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_1)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_2)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_3)));
Marcio Montenegro
fonte
0

em onCreatePreferences faça isso ::

SharedPreferences sharedPreferences =getPreferenceScreen().getSharedPreferences();
PreferenceScreen prefScreen = getPreferenceScreen();
int count = prefScreen.getPreferenceCount();

for (int i = 0; i < count; i++) {
  Preference p = prefScreen.getPreference(i);
    if (p instanceof ListPreference) {
       String value = sharedPreferences.getString(p.getKey(), "");
       ListPreference listPreference = (ListPreference) preference;
       int prefIndex = listPreference.findIndexOfValue(stringValue);
       if (prefIndex >= 0) {
            preference.setSummary(listPreference.getEntries()[prefIndex]);
      }
    }
 }  
Derrick Njeru
fonte