Измените сводку ListPreference с новым значением (Android)
Как я могу изменить сводку ListPreference к новой строке "Entry", выбранной пользователем (не значение записи)
Я подавляю его с помощью setOnPreferenceChangeListener(), но в
new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
return true;
}
}
используя ((ListPreference)preference).getEntry() Я получаю старое значение (потому что оно еще не изменилось), а newValue.toString() возвращает значение записи (не текст записи, отображаемый для пользователя)
Как мне это сделать? заранее спасибо
13 ответов
Просто установите итоговое значение %s
в описании XML.
РЕДАКТИРОВАТЬ: я проверил его на нескольких устройствах, и он не работает на самом деле. Это странно, потому что согласно документам это должно работать: ListPreference.getSummary ().
Но реализовать эту функциональность можно самостоятельно. Реализация требует наследования от ListPreference
учебный класс:
public class MyListPreference extends ListPreference {
public MyListPreference(final Context context) {
this(context, null);
}
public MyListPreference(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
@Override
public CharSequence getSummary() {
final CharSequence entry = getEntry();
final CharSequence summary = super.getSummary();
if (summary == null || entry == null) {
return null;
} else {
return String.format(summary.toString(), entry);
}
}
@Override
public void setValue(final String value) {
super.setValue(value);
notifyChanged();
}
}
Как вы видете MyListPreference
имеет собственное итоговое поле, которое может содержать маркеры форматирования. И когда значение предпочтения меняется, Preference.notifyChanged()
метод вызывается и вызывает MyListPreference.getSummary()
метод, который будет вызван из Preference.onBindView()
,
PS: этот подход не был достаточно протестирован, поэтому он может содержать ошибки.
%s
реализация глючит. Представление показывает правильное значение при первой загрузке (если задано значение списка по умолчанию), но представление не обновляется при выборе элемента списка. Вы должны установить флажок или другое предпочтение, чтобы обновить вид.
В качестве обходного пути внедрить OnSharedPreferenceChangeListener
переопределить сводку для предпочтения списка.
/src/apps/app_settings/SettingsActivity.java
package apps.app_settings;
import android.os.Bundle;
import android.preference.PreferenceActivity;
public class SettingsActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* set fragment */
getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit();
}
}
/src/apps/app_settings/SettingsFragment.java
package apps.app_settings;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
public class SettingsFragment extends PreferenceFragment implements OnSharedPreferenceChangeListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* set preferences */
addPreferencesFromResource(R.xml.preferences);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
/* get preference */
Preference preference = findPreference(key);
/* update summary */
if (key.equals("list_0")) {
preference.setSummary(((ListPreference) preference).getEntry());
}
}
@Override
public void onResume() {
super.onResume();
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onPause() {
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
super.onPause();
}
}
/res/xml/preferences.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:key="list_0"
android:title="@string/settings_list_0_title"
android:summary="%s"
android:entries="@array/settings_list_0_entries"
android:entryValues="@array/settings_list_0_entry_values"
android:defaultValue="@string/settings_list_0_default_value"/>
</PreferenceScreen>
/res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="settings_list_0_title">list 0</string>
<string-array name="settings_list_0_entries">
<item>item 0</item>
<item>item 1</item>
<item>item 2</item>
</string-array>
<string-array name="settings_list_0_entry_values">
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
<string name="settings_list_0_default_value">0</string>
</resources>
Я решил эту проблему с помощью другого простого https://gist.github.com/brunomateus/5617025:
public class ListPreferenceWithSummary extends ListPreference{
public ListPreferenceWithSummary(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListPreferenceWithSummary(Context context) {
super(context);
}
@Override
public void setValue(String value) {
super.setValue(value);
setSummary(value);
}
@Override
public void setSummary(CharSequence summary) {
super.setSummary(getEntry());
}
}
Это работало очень хорошо на моем устройстве GirgerBeard. Даже когда ваше приложение запускается впервые. Не забудьте указать значение по умолчанию для вашего xml-префикса:
android:defaultValue="default value"
и установить значения по умолчанию на вашем PreferenceActivity
или же PrefenceFragment
:
PreferenceManager.setDefaultValues(this, R.xml.you pref file, false);
Я рекомендую реализовать OnSharedPreferenceChangeListener в вашем PreferenceFragment или PreferenceActivity вместо Preference.setOnPreferenceChangeListner. Используйте setSummay, чтобы установить новые изменения. (Не забудьте зарегистрировать и отменить регистрацию слушателя.) Этот слушатель вызывается после того, как изменение в предпочтении было завершено. Вы также должны установить значение по умолчанию в XML для предпочтений.
Решение "%s" работает для меня на Android 4.0.3, записывая% s непосредственно в файл XML. Проблема в том, что текст не обновляется после того, как я изменил значение предпочтения, но это происходит, когда я изменяю другое предпочтение моего PreferenceScreen. Может быть, здесь не хватает обновления?
Это самый упрощенный способ, который я реализовал. Просто возьмите значения, заданные слушателем onPreferenceChange
ListPreference preference;
@Override
protected void onCreate(Bundle savedInstanceState) {
preference = (ListPreference)findPreference("myKey");
preference.setSummary(preferenceColorButtons.getEntry());
preference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
ListPreference listPreference = (ListPreference)preference;
int id = 0;
for (int i = 0; i < listPreference.getEntryValues().length; i++)
{
if(listPreference.getEntryValues()[i].equals(newValue.toString())){
id = i;
break;
}
}
preference.setSummary(listPreference.getEntries()[id]);
return true;
}
});
}
Насколько я знаю:
а)%s работает на Android 4, но не на 2.x.
б) Обновление достигается, если вы установите промежуточное значение между ними, см. здесь: /questions/19920842/nastrojki-predpochtenij-android-ne-obnovlyayutsya-pravilno/19920858#19920858
Нет необходимости расширять ListPreference или перебирать entryValues и т. Д.
public boolean onPreferenceChange(Preference preference, Object newValue) {
int i = ((ListPreference)preference).findIndexOfValue(newValue.toString());
CharSequence[] entries = ((ListPreference)preference).getEntries();
preference.setSummary(entries[i]);
return true;
}
Я знаю, что это очень старый вопрос, но он все еще актуален. Для автоматического обновления сводки вы должны вызвать исходный preferenceChangeListener:
final OnPreferenceChangeListener listener = preference.getOnPreferenceChangeListener();
preference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener()
{
@Override
public boolean onPreferenceChange(Preference preference, Object o)
{
if (listener !=null)
listener .onPreferenceChange(preference, o);
return true;
}
});
Ссылаясь на принятый ответ ( @Michael), если вы измените MyListPreference, чтобы добавить onPreferenceChangeListener:
public MyListPreference(final Context context, final AttributeSet attrs) {
super(context, attrs);
setOnPreferenceChangeListener(this);
}
и заставить реализацию слушателя возвращать true:
public boolean onPreferenceChange(Preference preference, Object newValue) {
// Do other stuff as needed, e.g. setTitle()
return true;
}
сводка "% s" всегда разрешается до последней настройки. В противном случае он всегда имеет настройку по умолчанию.
Не забудьте добавить инструменты:
public class MyListPreference extends ListPreference implements Preference.OnPreferenceChangeListener
Привет редактировал выше для EditText, если это помогает:)
package fr.bmigette.crocoschedulerconsoleandroid;
import android.content.Context;
import android.preference.EditTextPreference;
import android.util.AttributeSet;
/**
* Created by bastien on 28/07/2015.
*/
public class EditTextPreferenceWithSummary extends EditTextPreference{
public EditTextPreferenceWithSummary(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EditTextPreferenceWithSummary(Context context) {
super(context);
}
@Override
public void setText(String value) {
super.setText(value);
setSummary(value);
}
@Override
public void setSummary(CharSequence summary) {
super.setSummary(getText());
}
}
И создает файл preference.xml следующим образом:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:key="pref_key_category_host"
android:title="@string/title_category_host" >
<fr.bmigette.crocoschedulerconsoleandroid.EditTextPreferenceWithSummary
android:defaultValue="@string/default_pref_host_1"
android:key="pref_key_host_1"
android:summary="@string/default_pref_host_1"
android:title="@string/title_pref_host_1" />
<fr.bmigette.crocoschedulerconsoleandroid.EditTextPreferenceWithSummary
android:defaultValue="@string/default_pref_port_1"
android:key="pref_key_port_1"
android:summary="@string/default_pref_port_1"
android:title="@string/title_pref_port_1" />
<fr.bmigette.crocoschedulerconsoleandroid.EditTextPreferenceWithSummary
android:defaultValue="@string/default_pref_pass_1"
android:key="pref_key_pass_1"
android:summary="@string/default_pref_pass_1"
android:title="@string/title_pref_pass_1" />
</PreferenceCategory>
</PreferenceScreen>
Нет необходимости выполнять дополнительное кодирование, я столкнулся с этой проблемой и решил ее одной строкой.
После многих часов просмотра всех ответов на этот и другие подобные вопросы я нашел очень простой способ сделать это без расширения ListPreference
, вы можете сделать это совместно extends PreferenceActivity
см. код ниже.
public class UserSettingsActivity extends PreferenceActivity
{
ListPreference listpref;
@Override
public void onCreate(Bundle savedInstenceState)
{
super.onCreate(savedInstenceState);
addPreferencesFromResource(R.xml.settings);
listpref = (ListPreference)findPreference("prefDefaultCurrency");
listpref.setOnPreferenceChangeListener(new OnPreferenceChangeListener()
{
@Override
public boolean onPreferenceChange(Preference preference, Object value) {
// TODO Auto-generated method stub
listpref.setSummary(listpref.getEntries()[Integer.parseInt(value.toString())]);
return true;
}
});
Вот и все, что вам нужно сделать, - это получить значение, переданное из onPreferenceChange(Preference preference, Object value)
разобрать его в целое число и передать его listpref.setSummary(listpref.getEntries()[Integer.parseInt(value.toString())]);
Я также столкнулся с этой проблемой и, наконец, нашел решение, используя значение, полученное от слушателя. В моем примере ниже (для ListPreference) я сначала получаю индекс значения в массиве ListPreference, а затем извлекаю метку значения, используя этот индекс:
passwordFrequencyLP.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
int newFrequency = Integer.valueOf(newValue.toString());
prefs.edit().putInt("settings_key_password_frequency", newFrequency).commit();
//get the index of the new value selected in the ListPreference array
int index = passwordFrequencyLP.findIndexOfValue(String.valueOf(newValue));
//get the label of the new value selected
String label = (String) passwordFrequencyLP.getEntries()[index];
passwordFrequencyLP.setSummary(label);
makeToast(getResources().getString(R.string.password_frequency_saved));
return true;
}
});
Этот маленький трюк работает хорошо, я нашел много разных возможных решений этой проблемы, но только этот сработал для меня.
Самый простой способ в Котлине
findPreference<ListPreference>(getString(R.string.pref_some_key)).apply {
summary = entry
setOnPreferenceChangeListener { _, newValue ->
summary = entries[entryValues.indexOf(newValue)]
return@setOnPreferenceChangeListener true
}
}