使用新值更改ListPreference的摘要(Android)

时间:2011-08-10 20:08:27

标签: java android

如何将ListPreference的摘要修改为用户选择的新“Entry”字符串(而不是条目值)

我用setOnPreferenceChangeListener()来支持它,但是在

new OnPreferenceChangeListener() {

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

使用((ListPreference)首选项).getEntry()我得到旧值(因为它尚未更改),newValue.toString()返回条目值(不是显示给用户的条目文本)

我该怎么办?提前致谢

14 个答案:

答案 0 :(得分:38)

只需在xml说明中将汇总值设置为%s

编辑:我在几台设备上测试了它,但它确实无法正常工作。这很奇怪,因为根据文档,它必须有效: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。:这种方法尚未经过充分测试,因此可能包含错误。

答案 1 :(得分:9)

Nauman Zubair is right.

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

答案 2 :(得分:8)

我用另一个简单的solution (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 prefence上提供默认值:

android:defaultValue="default value"

并在PreferenceActivityPrefenceFragment上设置默认值:

 PreferenceManager.setDefaultValues(this, R.xml.you pref file, false);

答案 3 :(得分:3)

我建议在PreferenceFragment或PreferenceActivity中实现OnSharedPreferenceChangeListener,而不是Preference.setOnPreferenceChangeListner。使用setSummay设置新更改。 (不要忘记注册和取消注册侦听器。)在完成对首选项的更改后调用此侦听器。您还应该在XML中为首选项设置默认值。

答案 4 :(得分:2)

通过将%s直接写入XML文件,“%s”解决方案适用于android 4.0.3。问题是我更改了首选项的值后文本没有更新,但是当我修改我的PreferenceScreen的另一个首选项时。也许这里缺少一些刷新。

答案 5 :(得分:2)

这是我实施的最简化的方式。只需获取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;
        }
    });

}

答案 6 :(得分:1)

据我所知:

a)%s适用于android 4,但不适用于2.x。

b)如果您在其间设置虚拟值,则会实现更新,请参见此处:https://stackoverflow.com/a/16397539/1854563

答案 7 :(得分:1)

无需扩展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;
}

答案 8 :(得分:1)

我知道这是一个非常古老的问题,但它仍然是实际问题。 要自动更新摘要,您必须调用原始的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;
            }
        });

答案 9 :(得分:0)

我也遇到了这个问题,我终于通过使用来自监听器的值找到了解决方案。 在下面的示例中(对于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;
        }
    });

这个小技巧很有效,我找到了很多不同的解决方案来解决这个问题,但只有这个解决了这个问题。

答案 10 :(得分:0)

如果有帮助,请编辑上面的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>

答案 11 :(得分:0)

  

没有必要做那些额外的编码,我遇到了这个问题   并用一条线解决了。

经过几个小时查看此问题和其他类似问题的所有答案后,我发现了在不延长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())]);

答案 12 :(得分:0)

参考接受的答案(@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

答案 13 :(得分:0)

科特林最简单的方式

findPreference<ListPreference>(getString(R.string.pref_some_key)).apply {
    summary = entry
    setOnPreferenceChangeListener { _, newValue ->
        summary = entries[entryValues.indexOf(newValue)]
        return@setOnPreferenceChangeListener true
    }
}