Измените резюме ListPreference с новым значением (Android)

Как изменить сводку ListPreference на новую строку "Enter", выбранную пользователем (а не значение записи)

Я поддерживаю его с помощью setOnPreferenceChangeListener(), но в

new OnPreferenceChangeListener() {

        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            return true;
        }
    }

используя ((предпочтение ListPreference)).getEntry() Я получаю старое значение (потому что оно еще не изменено), а newValue.toString() возвращает значение записи (а не текст ввода, отображаемый пользователю)

Как я могу это сделать? Спасибо заранее

Ответ 1

Просто установите итоговое значение %s в описании xml.

EDIT. Я тестировал его на нескольких устройствах, и он не работает. Это странно, потому что согласно документам он должен работать: 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().

P.S.: Этот подход недостаточно проверен, поэтому он может содержать ошибки.

Ответ 2

Нуман Зубайр прав.

Реализация %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>

Ответ 3

Я решил эту проблему другим и простым решением (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);

Ответ 4

Я рекомендую реализовать OnSharedPreferenceChangeListener в вашем PreferenceFragment или PreferenceActivity вместо Preference.setOnPreferenceChangeListner. Используйте setSummay для установки новых изменений. (Не забудьте зарегистрировать и отменить регистрацию слушателя.) Этот слушатель вызывается после того, как изменение в предпочтении было завершено. Вы также должны установить значение по умолчанию в XML для предпочтений.

Ответ 5

Решение "% s" работает для меня на android 4.0.3, набрав% s непосредственно в файле XML. Проблема заключается в том, что текст не обновляется после того, как я изменил значение предпочтения, но это когда я изменяю другое предпочтение моего PreferenceScreen. Возможно, некоторые обновления отсутствуют здесь.

Ответ 6

Это самый упрощенный способ, который я реализовал. Просто возьмите значения, заданные слушателем 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;
        }
    });

}

Ответ 7

Все, что я знаю:

a)% s работает на android 4, но не на 2.x.

b) Обновление достигается, если вы установите значение фиктивного значения в промежутке, см. здесь: fooobar.com/questions/16930/...

Ответ 8

Нет необходимости расширять 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;
}

Ответ 9

Я знаю, что это очень старый вопрос, но он по-прежнему актуальный. Чтобы автоматически обновить сводку, вы должны вызвать исходную функцию предпочтенияChangeListener:

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

Ответ 10

Я также столкнулся с этой проблемой, и я, наконец, нашел решение, используя значение, исходящее от слушателя. В моем примере ниже (для 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;
        }
    });

Этот небольшой трюк работает хорошо, я нашел много разных возможных решений этой проблемы, но только этот работал у меня.

Ответ 11

Hi отредактировал выше для 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>

Ответ 12

Нет необходимости делать это дополнительное кодирование, я столкнулся с этой проблемой и решил его одной строкой.

После многих часов, рассматривающих все ответы в этом и других подобных вопросах, я обнаружил самый простой способ сделать это без расширения 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())]);

Ответ 13

Ссылаясь на принятый ответ (@Michael), если вы изменяете MyListPreference, чтобы добавить onPreferenceChangeListener:

public MyListPreference(final Context context, final AttributeSet attrs) {
    super(context, attrs);
    setOnPreferenceChangeListener(this);
}

а реализация listener возвращает 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