Preferencje listy Androida: czy podsumowanie jest wybraną wartością?

112

Mam działanie preferencji, które używa preferencji listy zdefiniowanych w moim pliku XML. Jak ustawić podsumowanie aktywności na liście na wybraną wartość?

Dziękuję Ci!

Fran Fitzpatrick
źródło

Odpowiedzi:

411

Najłatwiej to zrobić, jeśli Android zrobi to za Ciebie. Zakładając, że chcesz, aby podsumowanie było zgodne z wybraną wartością, możesz po prostu ustawić podsumowanie ListPreferencena"%s" używając XML lub setSummarymetody w Javie. Na przykład:

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

System Android zastąpi %sbieżącą wartością ciągu preferencji wyświetlaną przez ListPreferenceselektor 's. Podsumowanie listy zostanie również ustawione poprawnie, gdy wprowadzisz aktywność - nie musisz pisać żadnego specjalnego kodu, aby skonfigurować ją na początku.

Działa to również z AndroidX ListPreference.

Spędziłem zdecydowanie zbyt dużo czasu mucking ze SharedPreferencessłuchaczy zanim to odkryłem.

George Hilliard
źródło
1
Wiem! Uwielbiam te eleganckie rozwiązania. Tak proste, ale trudne do znalezienia;)
sgibly
7
Musiałem to połączyć z ręczną aktualizacją ... bo podsumowanie nie jest aktualizowane przy zmianie wartości ...
Renetik
4
Doskonała odpowiedź. Wierz lub nie, ale jest to udokumentowane: developer.android.com/reference/android/preference/…
Lior
1
Czy możesz potwierdzić, że potrzebujesz API> = 11 do "%s"? W moich testach "%s"nie działa z Gingerbread i wcześniejszymi wersjami.
andreas1724
1
@BaptisteCandellier dzięki za ostrzeżenie. Jeśli coś istnieje, zespół Androida wycofa to. Dodałem link do androidx.
George Hilliard
29

Możesz użyć, OnPreferenceChangeListeneraby dynamicznie zmienić podsumowanie. Problem polega na tym, że pobiera wybraną wartość (od android:entryValues), a nie podpis ( android:entries). W poniższym kodzie użyłem toString(), ale właściwym rozwiązaniem jest znalezienie podpisu dla wartości. Tak czy inaczej, pomysł działa:

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
źródło
18

Chciałem też osiągnąć coś podobnego, ale problem z https://stackoverflow.com/a/8155029/592025 polega na tym, że pokazuje wartość dla moich preferencji (np. 1, 2 3 itd.). Chcę pokazać wpis (ciąg czytelny dla człowieka) odpowiadający wybranej wartości.

Więc zmieniłem to w ten sposób i działa tak, jak tego potrzebuję.

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

Sztuczka polega na tym, aby użyć getEntry()zamiast getValue()i po zmianie wartości, ustawić wartość jawnie i odczytać wpis.

midhunhk
źródło
8

Myślę, że to, czego szukasz, jest o wiele prostsze niż myślisz, dodaj następującą linię kodu do swojego Preferenceprzedmiotu:

android:summary="%1$s"

Więc będzie wyglądać mniej więcej tak:

<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 Geek
źródło
4

Najpierw uzyskaj odwołanie do ListPreference w swoim onCreate. Możesz użyć findPreference (). Na przykład:

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

Następnie, po pierwszym załadowaniu działania i za każdym razem, gdy wartość preferencji zostanie zmieniona, użyj dowolnej metody, aby uzyskać wartość elementu ListPreference i ustaw podsumowanie za pomocą:

pref.setSummary(theNewString);
cottonBallPaws
źródło
2

To jest kod, którego używam, nie wywołuje on ręcznie metody setValue, ponieważ uważam, że jest to już zrobione na późniejszym etapie.

Oto przykład:

@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
źródło
0

To jest dokładnie to, co zrobiłem i działa świetnie. W onSharedPreferenceChangeListener po prostu sprawdzam klucz tego, co się zmienia, a następnie w przypadku ListPreferences konwertuję go z powrotem na czytelny dla człowieka (entry zamiast entryValue) za pomocą instrukcji if. Dość proste.

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

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

<?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
źródło
1
Idealnie byłoby, gdybyś czytał podsumowanie dynamicznie, więc nie musisz śledzić go w dwóch miejscach.
George Hilliard,
0

Oto rozszerzona wersja odpowiedzi midhunhk, która odnosi się również do pomocnego ciągu znaków „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'";
...

Dla jasności, android: summary jest usuwany z powiązanego pliku XML.

RudyF
źródło
0

A oto jeden ze sposobów radzenia sobie z podsumowującą aktualizacją preferencji dzwonka po wyborze użytkownika.

    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
źródło
0

Masz metodę bindPreferenceSummaryToValue na swoim PreferenceActivity,

możesz łatwo dodać podsumowanie do listy, wykonując następujące czynności:

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

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

W metodzie yout OnCreate wywołujesz funkcję bind w następujący sposób:

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

Możesz łatwo dodać inne podsumowanie w ten sam sposób:

bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_1)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_2)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_3)));
Marcio Montenegro
źródło
0

w onCreatePreferences zrób to:

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
źródło