Измените сводку 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
    }
}
Другие вопросы по тегам