Android-Listeneinstellungen: Zusammenfassung als ausgewählten Wert haben?

112

Ich habe eine Voreinstellungsaktivität, die Listeneinstellungen verwendet, wie sie in meiner XML-Datei definiert sind. Wie würde ich die Zusammenfassung der Listenaktivität auf den ausgewählten Wert setzen?

Danke dir!

Fran Fitzpatrick
quelle

Antworten:

410

Der einfachste Weg, dies zu tun, besteht darin, Android dies für Sie tun zu lassen. Angenommen, Sie möchten, dass die Zusammenfassung mit dem ausgewählten Wert übereinstimmt, können Sie die ZusammenfassungListPreference"%s" einfach so festlegen , dass entweder XML oder die setSummaryMethode in Java verwendet wird. Beispielsweise:

<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 wird durch %sden aktuellen Zeichenfolgenwert der Voreinstellung ersetzt, der von der ListPreferenceAuswahl des Benutzers angezeigt wird . Die Zusammenfassung der Liste wird auch beim Eingeben der Aktivität korrekt festgelegt. Sie müssen keinen speziellen Code schreiben, um sie zunächst einzurichten.

Dies funktioniert auch mit AndroidX ListPreference.

Ich habe viel zu viel Zeit damit verbracht, mich mit den SharedPreferencesZuhörern zu beschäftigen, bevor ich das entdeckte.

George Hilliard
quelle
1
Ich weiß! Ich liebe diese eleganten Lösungen. So einfach und doch schwer zu finden;)
wahrscheinlich
7
Ich musste diese witzige manuelle Aktualisierung kombinieren ... weil die Zusammenfassung nicht aktualisiert wird, wenn der Wert geändert wird ...
Renetik
4
Hervorragende Antwort. Ob Sie es glauben oder nicht, aber dies ist tatsächlich dokumentiert: developer.android.com/reference/android/preference/…
Lior
1
Können Sie bestätigen, dass Sie API> = 11 für benötigen "%s"? Funktioniert in meinen Tests "%s"nicht mit Lebkuchen und früheren Versionen.
andreas1724
1
@BaptisteCandellier danke für das Heads-up. Wenn etwas vorhanden ist, wird es vom Android-Team abgelehnt. Ich habe einen Link zu hinzugefügt androidx.
George Hilliard
29

Mit können Sie OnPreferenceChangeListenerdie Zusammenfassung dynamisch ändern. Das Problem ist, dass es den ausgewählten Wert (von android:entryValues) erhält , nicht die Beschriftung ( android:entries). Im folgenden Code habe ich verwendet toString(), aber die richtige Lösung besteht darin, die Beschriftung für den Wert zu finden. Wie auch immer, die Idee funktioniert:

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
quelle
18

Ich wollte auch etwas Ähnliches erreichen, aber das Problem mit https://stackoverflow.com/a/8155029/592025 ist, dass es den Wert für meine Präferenz anzeigt (wie 1, 2 3 usw.). Ich möchte den Eintrag (lesbare Zeichenfolge) anzeigen, der dem ausgewählten Wert entspricht.

Also habe ich es so geändert und arbeite so, wie ich es brauche.

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

Der Trick besteht darin, getEntry()anstelle getValue()und nach Änderung des Werts den Wert explizit festzulegen und den Eintrag zurückzulesen.

midhunhk
quelle
8

Ich denke, dass das, wonach Sie suchen, viel einfacher ist, als Sie denken können. Fügen Sie Ihrem PreferenceArtikel die folgende Codezeile hinzu :

android:summary="%1$s"

Es wird also ungefähr so ​​aussehen:

<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
quelle
4

Holen Sie sich zuerst einen Verweis auf die ListPreference in Ihrem onCreate. Sie können findPreference () verwenden. Beispielsweise:

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

Verwenden Sie dann beim ersten Laden der Aktivität und beim Ändern des Voreinstellungswerts eine beliebige Methode, um den Wert der ListPreference abzurufen, und legen Sie die Zusammenfassung fest mit:

pref.setSummary(theNewString);
CottonBallPaws
quelle
2

Dies ist der Code, den ich verwende. Er ruft setValue nicht manuell auf, da ich glaube, dass dies bereits zu einem späteren Zeitpunkt erfolgt.

Hier ist ein Beispiel:

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

Genau das habe ich getan und es funktioniert großartig. Im onSharedPreferenceChangeListener überprüfe ich einfach den Schlüssel, der geändert wird, und konvertiere ihn dann für ListPreferences mit den if-Anweisungen zurück in den lesbaren Wert (Eintrag anstelle von entryValue). Ziemlich einfach.

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

XML-Layout

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

Jordan Hochstetler
quelle
1
Idealerweise lesen Sie die Zusammenfassung dynamisch, damit Sie sie nicht an zwei Stellen nachverfolgen müssen.
George Hilliard
0

Hier ist eine erweiterte Version von Midhunhks Antwort, die sich auch mit der hilfreichen Zeichenfolge "android: summary" befasst

        // 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'";
...

Und um ganz klar zu sein, android: summary wird aus der zugehörigen XML entfernt.

RudyF
quelle
0

Und hier ist eine Möglichkeit, das zusammenfassende Update der Klingeltoneinstellung nach einer Benutzerauswahl zu verarbeiten.

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

Sie haben eine Methode bindPreferenceSummaryToValue für Ihre PreferenceActivity.

Sie können die Zusammenfassung einfach wie folgt zur Liste hinzufügen:

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

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

Bei Ihrer OnCreate-Methode rufen Sie die Bindefunktion folgendermaßen auf:

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

Sie können andere Zusammenfassungen auf die gleiche Weise hinzufügen:

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

unter onCreatePreferences tun Sie dies ::

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
quelle