Preferencias de la lista de Android: ¿tiene un resumen como valor seleccionado?

112

Tengo una actividad de preferencias que utiliza una lista de preferencias según lo definido por mi archivo XML. ¿Cómo establecería el resumen de la actividad de la lista en el valor seleccionado?

¡Gracias!

Fran Fitzpatrick
fuente

Respuestas:

410

La forma más sencilla de hacer esto es que Android lo haga por usted. Suponiendo que desea que el resumen coincida con el valor seleccionado, simplemente puede configurar el resumen del ListPreferencea"%s" usando XML o el setSummarymétodo en Java. Por ejemplo:

<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 reemplazará %scon el valor de cadena actual de la preferencia, como se muestra en elListPreference selector de. El resumen de la lista también se configurará correctamente cuando ingrese a la actividad; no es necesario que escriba ningún código especial para configurarla inicialmente.

Esto también funciona con AndroidX ListPreference.

Pasé mucho demasiado tiempo limpiando con SharedPreferenceslos oyentes antes de descubrir esto.

George Hilliard
fuente
1
¡Lo sé! Amo esas elegantes soluciones. Tan simple, pero difícil de encontrar;)
sgbly
7
Tuve que combinar esta actualización manual ingeniosa ... porque el resumen no se actualiza cuando se cambia el valor ...
Renetik
4
Excelente respuesta. Lo crea o no, pero esto está realmente documentado: developer.android.com/reference/android/preference/…
Lior
1
¿Puede confirmar que necesita API> = 11 para "%s"? En mis pruebas, "%s"no funciona con Gingerbread y versiones anteriores.
andreas1724
1
@BaptisteCandellier gracias por el aviso. Si existe algo, el equipo de Android lo desaprobará. Agregué un enlace a androidx.
George Hilliard
29

Puede utilizar OnPreferenceChangeListenerpara cambiar dinámicamente el resumen. El problema es que obtiene el valor seleccionado (de android:entryValues), no el título ( android:entries). En el siguiente código que utilicé toString(), pero la solución adecuada es encontrar el título del valor. De todos modos, la idea 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
fuente
18

También quería lograr algo similar, pero el problema con https://stackoverflow.com/a/8155029/592025 es que muestra el valor de mi preferencia (como 1, 2 3, etc.). Quiero mostrar la entrada (cadena legible por humanos) correspondiente al valor seleccionado.

Así que lo cambié de esta manera y funciona como lo necesito.

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

El truco es usar en getEntry()lugar de getValue()y una vez que se cambia el valor, establecer el valor explícitamente y volver a leer la entrada.

Midhunhk
fuente
8

Creo que lo que está buscando es mucho más simple de lo que puede pensar, agregue la siguiente línea de código a su Preferenceartículo:

android:summary="%1$s"

Entonces se verá algo como esto:

<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" />
42 Friki
fuente
4

Primero obtenga una referencia a ListPreference en su onCreate. Puede usar findPreference (). Por ejemplo:

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

Luego, cuando cargue la Actividad por primera vez y siempre que se cambie el valor de las preferencias, use el método que desee para obtener el valor de ListPreference y configure el resumen con:

pref.setSummary(theNewString);
cottonBallPaws
fuente
2

Este es el código que estoy usando, no llama a setValue manualmente, ya que creo que esto ya está hecho en una etapa posterior.

Aquí hay un ejemplo:

@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
fuente
0

Esto es exactamente lo que hice y funciona muy bien. En onSharedPreferenceChangeListener , simplemente verifico la clave de lo que se está cambiando y luego, para ListPreferences, la convierto nuevamente a la lectura humana (entrada en lugar de entryValue) con las declaraciones if. Bastante simple.

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

diseño 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"
        />

matriz 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
fuente
1
Lo ideal sería leer el resumen de forma dinámica para no tener que realizar un seguimiento de él en dos lugares.
George Hilliard
0

Aquí hay una versión ampliada de la respuesta de midhunhk que también aborda la útil cadena "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'";
...

Y, para que quede claro, android: summary se elimina del xml relacionado.

RudyF
fuente
0

Y aquí hay una forma de lidiar con la actualización resumida de la preferencia de tono de llamada después de una selección de usuario.

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

Tiene un método bindPreferenceSummaryToValue en su PreferenceActivity,

puede agregar fácilmente el resumen a la lista haciendo así:

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

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

En su método OnCreate, llama a la función de vinculación de esta manera:

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

Puede agregar fácilmente otros resúmenes de la misma manera:

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

en onCreatePreferences haz esto:

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
fuente