Preferenze elenco Android: hai il riepilogo come valore selezionato?


112

Ho un'attività di preferenza che utilizza un elenco di preferenze come definito dal mio file XML. Come impostare il riepilogo dell'attività dell'elenco sul valore selezionato?

Grazie!

Risposte:


410

Il modo più semplice per farlo è solo quello di farlo fare ad Android per te. Supponendo che si desideri che il riepilogo corrisponda al valore selezionato, è possibile semplicemente impostare il riepilogo di ListPreferencesu"%s" utilizzando XML o il setSummarymetodo in Java. Per esempio:

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

Android sostituirà %scon il valore di stringa corrente della preferenza, come visualizzato dal ListPreferenceselettore di. Anche il riepilogo dell'elenco verrà impostato correttamente quando si immette l'attività: non è necessario scrivere alcun codice speciale per impostarlo inizialmente.

Questo funziona anche con l'AndroidX ListPreference.

Ho passato gran lunga troppo tempo pasticciare con SharedPreferencesgli ascoltatori, prima ho scoperto questo.


1
Lo so! Adoro quelle soluzioni eleganti. Così semplice, ma difficile da trovare;)
sgargabilmente

7
Ho dovuto combinare questo spirito di aggiornamento manuale ... perché il riepilogo non viene aggiornato quando il valore viene modificato ...
Renetik

4
Ottima risposta. Che ci crediate o no, ma in realtà è documentato: developer.android.com/reference/android/preference/…
Lior

1
Puoi confermare che hai bisogno di API> = 11 per "%s"? Nei miei test, "%s"non funziona con Gingerbread e versioni precedenti.
andreas1724

1
@BaptisteCandellier, grazie per l'avvertimento. Se esiste qualcosa, il team Android lo deprecerà. Ho aggiunto un collegamento a androidx.
George Hilliard

29

È possibile utilizzare OnPreferenceChangeListenerper modificare dinamicamente il riepilogo. Il problema è che ottiene il valore selezionato (da android:entryValues), non la didascalia ( android:entries). Nel codice seguente ho usato toString(), ma la soluzione corretta è trovare la didascalia per il valore. Comunque, l'idea funziona:

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

18

Volevo anche ottenere qualcosa di simile, ma il problema con https://stackoverflow.com/a/8155029/592025 è che mostra il valore per la mia preferenza (come 1, 2 3 ecc.). Voglio mostrare la voce (stringa leggibile dall'uomo) corrispondente al valore selezionato.

Quindi l'ho cambiato in questo modo e funziona nel modo in cui ne ho bisogno.

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

Il trucco è usare al getEntry()posto di getValue()e una volta modificato il valore, impostare il valore in modo esplicito e rileggere la voce.


8

Penso che quello che stai cercando sia molto semplice che tu possa pensare, aggiungi la seguente riga di codice al tuo Preferencearticolo:

android:summary="%1$s"

Quindi sarà simile a questo:

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

4

Per prima cosa ottieni un riferimento a ListPreference nel tuo onCreate. Puoi usare findPreference (). Per esempio:

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

Quindi, quando carichi per la prima volta l'attività e ogni volta che il valore delle preferenze viene modificato, utilizza il metodo che desideri per ottenere il valore di ListPreference e imposta il riepilogo con:

pref.setSummary(theNewString);

2

Questo è il codice che sto usando, non chiama setValue manualmente, poiché credo che questo sia già stato fatto in una fase successiva.

Ecco un esempio:

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

0

Questo è esattamente quello che ho fatto e funziona benissimo. In onSharedPreferenceChangeListener controllo semplicemente la chiave di ciò che viene modificato e quindi per ListPreferences lo converto di nuovo in Human readable (entry invece di entryValue) con le istruzioni if. Abbastanza semplice.

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

xml array

<?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>


1
Idealmente dovresti leggere il riepilogo in modo dinamico in modo da non doverlo tenere traccia in due punti.
George Hilliard

0

Ecco una versione estesa della risposta di midhunhk che affronta anche l'utile stringa "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, tanto per essere chiari, android: summary viene rimosso dal relativo xml.


0

Ed ecco un modo per gestire l'aggiornamento del riepilogo della preferenza della suoneria a seguito di una selezione dell'utente.

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

0

Hai un metodo bindPreferenceSummaryToValue sulla tua PreferenceActivity,

puoi facilmente aggiungere il riepilogo all'elenco in questo modo:

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

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

Sul tuo metodo OnCreate chiami la funzione bind in questo modo:

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

Puoi facilmente aggiungere altri riepiloghi allo stesso modo:

bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_1)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_2)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_3)));

0

sotto onCreatePreferences fai questo:

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]);
      }
    }
 }  
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.