Préférences de liste Android: avez-vous un résumé comme valeur sélectionnée?

112

J'ai une activité de préférence qui utilise une liste de préférences telle que définie par mon fichier XML. Comment définir le résumé de l'activité de liste sur la valeur sélectionnée?

Je vous remercie!

Fran Fitzpatrick
la source

Réponses:

410

Le moyen le plus simple de le faire est simplement de laisser Android le faire pour vous. En supposant que vous souhaitiez que le résumé corresponde à la valeur sélectionnée, vous pouvez simplement définir le résumé du sur ListPreferenceà l'"%s" aide de XML ou de la setSummaryméthode Java. Par exemple:

<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 remplacera %spar la valeur de chaîne actuelle de la préférence, telle qu'affichée par le ListPreferencesélecteur de. Le résumé de la liste sera également défini correctement lorsque vous entrerez dans l'activité - vous n'avez pas à écrire de code spécial pour la configurer initialement.

Cela fonctionne également avec AndroidX ListPreference.

J'ai passé beaucoup trop de temps à jouer avec les SharedPreferencesauditeurs avant de découvrir cela.

George Hilliard
la source
1
Je connais! J'adore ces solutions élégantes. Si simple, mais difficile à trouver;)
sgably
7
J'ai dû combiner cet esprit de mise à jour manuelle ... car le résumé n'est pas mis à jour lorsque la valeur est modifiée ...
Renetik
4
Excellente réponse. Croyez-le ou non, mais cela est en fait documenté: developer.android.com/reference/android/preference/...
Lior
1
Pouvez-vous confirmer que vous avez besoin d'API> = 11 pour "%s"? Dans mes tests, "%s"ne fonctionne pas avec Gingerbread et les versions antérieures.
andreas1724
1
@BaptisteCandellier merci pour le heads-up. Si quelque chose existe, l'équipe Android le désapprouvera. J'ai ajouté un lien vers androidx.
George Hilliard
29

Vous pouvez utiliser OnPreferenceChangeListenerpour modifier dynamiquement le résumé. Le problème est qu'il obtient la valeur sélectionnée (de android:entryValues), pas la légende ( android:entries). Dans le code suivant, j'ai utilisé toString(), mais la solution appropriée est de trouver la légende de la valeur. Quoi qu'il en soit, l'idée fonctionne:

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
la source
18

Je voulais aussi réaliser quelque chose de similaire, mais le problème avec https://stackoverflow.com/a/8155029/592025 est que, il montre la valeur de ma préférence (comme 1, 2 3, etc.). Je veux afficher l'entrée (chaîne lisible par l'homme) correspondant à la valeur sélectionnée.

Alors je l'ai changé de cette façon et fonctionne comme j'en ai besoin.

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

L'astuce consiste à utiliser getEntry()au lieu de getValue()et une fois que la valeur est modifiée, pour définir la valeur explicitement et relire l'entrée.

midhunhk
la source
8

Je pense que ce que vous recherchez est beaucoup plus simple que vous pouvez penser, ajoutez la ligne de code suivante à votre Preferenceélément:

android:summary="%1$s"

Cela ressemblera donc à quelque chose comme ceci:

<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
la source
4

Obtenez d'abord une référence à ListPreference dans votre onCreate. Vous pouvez utiliser findPreference (). Par exemple:

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

Ensuite, lorsque vous chargez l'activité pour la première fois et chaque fois que la valeur des préférences est modifiée, utilisez la méthode de votre choix pour obtenir la valeur de ListPreference et définissez le résumé avec:

pref.setSummary(theNewString);
cotonBallPaws
la source
2

C'est le code que j'utilise, il n'appelle pas setValue manuellement, car je pense que cela est déjà fait à un stade ultérieur.

Voici un exemple:

@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
la source
0

C'est exactement ce que j'ai fait et cela fonctionne très bien. Dans le onSharedPreferenceChangeListener, je vérifie simplement la clé de ce qui est changé, puis pour ListPreferences, je le reconvertis en lisible par l'homme (entrée au lieu de entryValue) avec les instructions if. Assez 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);
        }

mise en page 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"
        />

tableau 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
la source
1
Idéalement, vous liriez le résumé de manière dynamique afin de ne pas avoir à le suivre à deux endroits.
George Hilliard
0

Voici une version développée de la réponse de midhunhk qui traite également de la chaîne utile "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'";
...

Et, pour être clair, android: summary est supprimé du xml associé.

RudyF
la source
0

Et voici une façon de gérer la mise à jour récapitulative de la préférence de sonnerie après une sélection d'utilisateur.

    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
la source
0

Vous avez une méthode bindPreferenceSummaryToValue sur votre PreferenceActivity,

vous pouvez facilement ajouter le résumé à la liste en procédant comme suit:

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

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

Sur votre méthode OnCreate, vous appelez la fonction de liaison comme ceci:

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

Vous pouvez facilement ajouter d'autres récapitulatifs de la même manière:

bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_1)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_2)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_3)));
Marcio Monténégro
la source
0

sous onCreatePreferences, faites ceci:

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
la source