Настройки списка Android: иметь сводку в качестве выбранного значения?

112

У меня есть действие Preference, в котором используется список настроек, определенный в моем XML-файле. Как мне установить для сводки активности списка выбранное значение?

Спасибо!

Фрэн Фицпатрик
источник

Ответы:

411

Самый простой способ сделать это - попросить Android сделать это за вас. Предполагая, что вы хотите, чтобы сводка соответствовала выбранному значению, вы можете просто установить сводку ListPreferenceдля"%s" использования либо XML, либо setSummaryметода в Java. Например:

<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 заменит %sтекущее строковое значение предпочтения, как показано в ListPreferenceсредстве выбора. Сводка списка также будет правильно настроена при входе в действие - вам не нужно писать какой-либо специальный код для его первоначальной настройки.

Это также работает с AndroidX ListPreference.

Я потратил далеко слишком много времени отвода с SharedPreferencesслушателями , прежде чем я узнал об этом.

Джордж Хиллиард
источник
1
Я знаю! Мне нравятся эти элегантные решения. Так просто, но трудно найти;)
sgably
7
Мне пришлось комбинировать это обновление вручную ... потому что сводка не обновляется при изменении значения ...
Ренетик
4
Отличный ответ. Вы не поверите, но это действительно задокументировано: developer.android.com/reference/android/preference/…
Лиор,
1
Вы можете подтвердить, что вам нужен API> = 11 "%s"? В моих тестах "%s"не работает с Gingerbread и более ранними версиями.
andreas1724
1
@BaptisteCandellier, спасибо за предупреждение. Если что-то существует, команда Android откажется от этого. Я добавил ссылку на androidx.
Джордж Хиллиард
29

Вы можете использовать OnPreferenceChangeListenerдля динамического изменения сводки. Проблема в том, что он получает выбранное значение (из android:entryValues), а не заголовок ( android:entries). В следующем коде я использовал toString(), но правильное решение - найти заголовок для значения. В любом случае, идея работает:

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
источник
18

Я также хотел добиться чего-то подобного, но проблема с https://stackoverflow.com/a/8155029/592025 заключается в том, что он показывает значение для моих предпочтений (например, 1, 2 3 и т. Д.). Я хочу показать запись (удобочитаемую строку), соответствующую выбранному значению.

Поэтому я изменил его так, и теперь он работает так, как мне нужно.

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

Хитрость заключается в том, чтобы getEntry()вместо getValue()и после изменения значения явно установить значение и прочитать запись.

midhunhk
источник
8

Я думаю, что то, что вы ищете, намного проще, чем вы можете подумать, добавьте следующую строку кода в свой Preferenceэлемент:

android:summary="%1$s"

Это будет выглядеть примерно так:

<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
источник
4

Сначала получите ссылку на ListPreference в своем onCreate. Вы можете использовать findPreference (). Например:

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

Затем, когда вы впервые загружаете Activity и всякий раз, когда значение предпочтений изменяется, используйте любой метод, который вы хотите получить, чтобы получить значение ListPreference, и установите сводку с помощью:

pref.setSummary(theNewString);
хлопокШарикЛапы
источник
2

Это код, который я использую, он не вызывает setValue вручную, поскольку я считаю, что это уже сделано на более позднем этапе.

Вот пример:

@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

Это именно то, что я сделал, и это отлично работает. В onSharedPreferenceChangeListener я просто проверяю ключ того, что изменяется, а затем для ListPreferences конвертирую его обратно в удобочитаемый (запись вместо entryValue) с помощью операторов if. Довольно просто.

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 массив

<?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
В идеале вы должны читать резюме динамически, чтобы вам не приходилось отслеживать его в двух местах.
Джордж Хиллиард
0

Вот расширенная версия ответа midhunhk, которая также касается полезной строки «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'";
...

И, для ясности, android: summary удален из соответствующего xml.

RudyF
источник
0

И вот один из способов справиться с обновлением сводки предпочтений мелодии звонка после выбора пользователя.

    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
источник
0

У вас есть метод bindPreferenceSummaryToValue в вашем PreferenceActivity,

вы можете легко добавить резюме в список, выполнив следующие действия:

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

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

В вашем методе OnCreate вы вызываете функцию привязки следующим образом:

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

Таким же образом вы можете легко добавить другие резюме:

bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_1)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_2)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_3)));
Марсио Монтенегро
источник
0

в onCreatePreferences сделайте следующее:

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]);
      }
    }
 }  
Деррик Ньеру
источник