Как отобразить текущее значение предпочтения Android в сводке настроек? - PullRequest
442 голосов
/ 10 февраля 2009

Это должно появляться очень часто.

Когда пользователь редактирует настройки в приложении для Android, я бы хотел, чтобы они могли видеть текущее установленное значение предпочтения в сводке Preference.

Пример: если у меня есть параметр Предпочтения для «Отменить старые сообщения», который указывает количество дней, после которых сообщения должны быть очищены. В PreferenceActivity я бы хотел, чтобы пользователь увидел:

"Отменить старые сообщения" <- title </p>

«Очистить сообщения после x дней» <- <a href="http://code.google.com/android/reference/android/preference/Preference.html#setSummary(java.lang.CharSequence)" rel="noreferrer"> сводка , где x - текущее значение предпочтения

Дополнительный кредит: сделайте это повторно используемым, чтобы я мог легко применить его ко всем моим предпочтениям независимо от их типа (чтобы он работал с EditTextPreference, ListPreference и т. Д. С минимальным количеством кода).

Ответы [ 32 ]

11 голосов
/ 20 февраля 2014

Для EditTextPreference:

public class MyEditTextPreference extends EditTextPreference {
    public MyEditTextPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public MyEditTextPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setText(String text) {
        super.setText(text);
        setSummary(text);
    }
}
8 голосов
/ 27 июля 2015

Если кто-то все еще ищет ответы на этот вопрос, вам следует проверить тридцать три комфортных с ответа.

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

7 голосов
/ 21 ноября 2010

Спасибо за этот совет!

У меня есть один экран предпочтений, и я хочу показать значение для каждого предпочтения списка в качестве сводки.

Это мой путь сейчас:

public class Preferences extends PreferenceActivity implements OnSharedPreferenceChangeListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences);
}

@Override
protected void onResume() {
    super.onResume();

    // Set up initial values for all list preferences
    Map<String, ?> sharedPreferencesMap = getPreferenceScreen().getSharedPreferences().getAll();
    Preference pref;
    ListPreference listPref;
    for (Map.Entry<String, ?> entry : sharedPreferencesMap.entrySet()) {
        pref = findPreference(entry.getKey());
        if (pref instanceof ListPreference) {
            listPref = (ListPreference) pref;
            pref.setSummary(listPref.getEntry());
        }
    }

    // Set up a listener whenever a key changes            
    getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}

@Override
protected void onPause() {
    super.onPause();

    // Unregister the listener whenever a key changes            
    getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);    
}

public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    Preference pref = findPreference(key);

    if (pref instanceof ListPreference) {
        ListPreference listPref = (ListPreference) pref;
        pref.setSummary(listPref.getEntry());
    }
}

Это работает для меня, но мне интересно, какое решение лучше (производительность, стабильность, масштабируемость): то, что показывает Koem, или это?

6 голосов
/ 29 мая 2010

Спасибо, Рето, за подробное объяснение!

В случае, если это кому-нибудь поможет, мне пришлось изменить код, предложенный Reto Meier, чтобы он работал с SDK для Android 1.5

@Override
protected void onResume() {
    super.onResume();

    // Setup the initial values
    mListPreference.setSummary("Current value is " + mListPreference.getEntry().toString()); 

    // Set up a listener whenever a key changes            
    ...
}

То же изменение относится к функции обратного вызова onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)

Приветствия

Chris

4 голосов
/ 05 июля 2012

Я решил проблему со следующим потомком ListPreference:

public class EnumPreference extends ListPreference {

    public EnumPreference(Context aContext, AttributeSet attrs) {
        super(aContext,attrs);
    }

    @Override
    protected View onCreateView(ViewGroup parent) {
        setSummary(getEntry());
        return super.onCreateView(parent);
    }

    @Override
    protected boolean persistString(String aNewValue) {
        if (super.persistString(aNewValue)) {
            setSummary(getEntry());
            notifyChanged();
            return true;
        } else {
            return false;
        }
    }
}

Кажется, у меня нормально работает в 1.6 до 4.0.4.

4 голосов
/ 27 апреля 2013
public class ProfileManagement extends PreferenceActivity implements
OnPreferenceChangeListener {
    EditTextPreference screenName;
    ListPreference sex;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.layout.profile_management);

            screenName = (EditTextPreference) findPreference("editTextPref");
            sex = (ListPreference) findPreference("sexSelector");

            screenName.setOnPreferenceChangeListener(this);
            sex.setOnPreferenceChangeListener(this);

    }   

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        preference.setSummary(newValue.toString());
        return true;
    }
}
4 голосов
/ 18 мая 2012

Я видел, как все проголосовавшие ответы показывают, как установить итоговое значение с точным текущим значением, но ОП также хотел что-то вроде:

«Очистить сообщения после x дней» * <- сводка, где <strong>x - текущее значение предпочтения

Вот мой ответ для достижения этого

Как документация говорит о ListPreference.getSummary():

Возвращает сводку этой ListPreference. Если в сводке есть маркер форматирования строки (то есть "% s" или "% 1 $ s"), то текущий вместо него будет подставлено значение записи.

Однако я пробовал на нескольких устройствах, и это не похоже на работу. С некоторыми исследованиями я нашел хорошее решение в этом ответе . Он просто состоит из расширения каждого используемого вами Preference и переопределения getSummary() для работы в соответствии с документацией Android.

3 голосов
/ 16 июля 2013

Вот мое решение:

Создание метода предпочтения типа getter.

protected String getPreference(Preference x) {
    // http://stackoverflow.com/questions/3993982/how-to-check-type-of-variable-in-java
    if (x instanceof CheckBoxPreference)
        return "CheckBoxPreference";
    else if (x instanceof EditTextPreference)
        return "EditTextPreference";
    else if (x instanceof ListPreference)
        return "ListPreference";
    else if (x instanceof MultiSelectListPreference)
        return "MultiSelectListPreference";
    else if (x instanceof RingtonePreference)
        return "RingtonePreference";
    else if (x instanceof SwitchPreference)
        return "SwitchPreference";
    else if (x instanceof TwoStatePreference)
        return "TwoStatePreference";
    else if (x instanceof DialogPreference) // Needs to be after ListPreference
        return "DialogPreference";
    else
        return "undefined";
}

Создание метода setSummaryInit.

public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
        Log.i(TAG, "+ onSharedPreferenceChanged(prefs:" + prefs + ", key:" + key + ")");
        if( key != null ) {
            updatePreference(prefs, key);
            setSummary(key);
        } else {
            Log.e(TAG, "Preference without key!");
        }
        Log.i(TAG, "- onSharedPreferenceChanged()");
    }

    protected boolean setSummary() {
        return _setSummary(null);
    }

    protected boolean setSummary(String sKey) {
        return _setSummary(sKey);
    }

    private boolean _setSummary(String sKey) {
        if (sKey == null) Log.i(TAG, "Initializing");
        else Log.i(TAG, sKey);

        // Get Preferences
        SharedPreferences sharedPrefs = PreferenceManager
                .getDefaultSharedPreferences(this);

        // Iterate through all Shared Preferences
        // http://stackoverflow.com/questions/9310479/how-to-iterate-through-all-keys-of-shared-preferences
        Map<String, ?> keys = sharedPrefs.getAll();
        for (Map.Entry<String, ?> entry : keys.entrySet()) {
            String key = entry.getKey();
            // Do work only if initializing (null) or updating specific preference key
            if ( (sKey == null) || (sKey.equals(key)) ) {
                String value = entry.getValue().toString();
                Preference pref = findPreference(key);
                String preference = getPreference(pref);
                Log.d("map values", key + " | " + value + " | " + preference);
                pref.setSummary(key + " | " + value + " | " + preference);
                if (sKey != null) return true;
            }
        }
        return false;
    }

    private void updatePreference(SharedPreferences prefs, String key) {
        Log.i(TAG, "+ updatePreference(prefs:" + prefs + ", key:" + key + ")");
        Preference pref = findPreference(key);
        String preferenceType = getPreference(pref);
        Log.i(TAG, "preferenceType = " + preferenceType);
        Log.i(TAG, "- updatePreference()");
    }

Initialize

Создать открытый класс, который PreferenceActivity и реализует OnSharedPreferenceChangeListener

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    PreferenceManager.setDefaultValues(this, R.xml.global_preferences,
    false);
    this.addPreferencesFromResource(R.xml.global_preferences);
    this.getPreferenceScreen().getSharedPreferences()
        .registerOnSharedPreferenceChangeListener(this);
}

protected void onResume() {
    super.onResume();
    setSummary();
}
3 голосов
/ 06 сентября 2015

FYI:

findPreference(CharSequence key)
This method was deprecated in API level 11. This function is not relevant
for a modern fragment-based PreferenceActivity.

Еще одна причина, чтобы взглянуть на очень тонкий Answer из @ASD выше ( источник найден здесь ), говорящий об использовании %s в android:summary для каждого поля в preferences.xml. (Текущее значение предпочтения заменяется на %s.)

enter image description here

<ListPreference
 ...        
 android:summary="Length of longest word to return as match is %s"
 ...
 />
3 голосов
/ 28 декабря 2012

Если вы хотите отображать только текстовое значение каждого поля в качестве сводки, следующий код должен быть самым простым в обслуживании Требуются только два изменения (строки 13 и 21, помеченные «изменить здесь»):

package com.my.package;

import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;

public class PreferencesActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {

    private final String[] mAutoSummaryFields = { "pref_key1", "pref_key2", "pref_key3" }; // change here
    private final int mEntryCount = mAutoSummaryFields.length;
    private Preference[] mPreferenceEntries;

    @SuppressWarnings("deprecation")
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preferences_file); // change here
        mPreferenceEntries = new Preference[mEntryCount];
        for (int i = 0; i < mEntryCount; i++) {
            mPreferenceEntries[i] = getPreferenceScreen().findPreference(mAutoSummaryFields[i]);
        }
    }

    @SuppressWarnings("deprecation")
    @Override
    protected void onResume() {
        super.onResume();
        for (int i = 0; i < mEntryCount; i++) {
            updateSummary(mAutoSummaryFields[i]); // initialization
        }
        getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this); // register change listener
    }

    @SuppressWarnings("deprecation")
    @Override
    protected void onPause() {
        super.onPause();
        getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this); // unregister change listener
    }

    private void updateSummary(String key) {
        for (int i = 0; i < mEntryCount; i++) {
            if (key.equals(mAutoSummaryFields[i])) {
                if (mPreferenceEntries[i] instanceof EditTextPreference) {
                    final EditTextPreference currentPreference = (EditTextPreference) mPreferenceEntries[i];
                    mPreferenceEntries[i].setSummary(currentPreference.getText());
                }
                else if (mPreferenceEntries[i] instanceof ListPreference) {
                    final ListPreference currentPreference = (ListPreference) mPreferenceEntries[i];
                    mPreferenceEntries[i].setSummary(currentPreference.getEntry());
                }
                break;
            }
        }
    }

    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        updateSummary(key);
    }

}
...