Android列表偏好设置:将摘要作为选定值吗?

121

我有一个首选项活动,它使用由我的XML文件定义的列表首选项。如何将列表活动的总结设置为所选值?

12个回答

429
最简单的方法就是让Android为您完成。假设您希望摘要与所选值匹配,您可以使用XML或Java中的`setSummary`方法,将`ListPreference`的摘要设置为`"%s"`。例如:

只需将ListPreference的摘要设置为"%s"即可

<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将使用ListPreference选择器显示的当前字符串值替换%s。当你进入活动时,列表摘要也将被正确设置 - 你不需要编写任何特殊代码来进行初始设置。
这也适用于AndroidX ListPreference
在我发现这个方法之前,我花费了太多时间来处理SharedPreferences监听器。

1
我知道!我喜欢那些优雅的解决方案。它们很简单,但很难找到 ;) - sgibly
7
我必须将这个与手动更新结合起来,因为当值被改变时,摘要并没有被更新... - Renetik
5
非常好的回答。信不信由你,但实际上这是有文献支持的: http://developer.android.com/reference/android/preference/ListPreference.html#setSummary(java.lang.CharSequence) - Lior
1
你能确认一下,"%s" 需要 API 版本大于等于 11 吗?在我的测试中,"%s" 在 Gingerbread 和之前的版本上无法正常工作。 - andreas1724
1
@BaptisteCandellier 谢谢你提醒。如果某个东西存在,Android团队会将其弃用。我已经添加了一个androidx的链接。 - George Hilliard
显示剩余6条评论

28

您可以使用OnPreferenceChangeListener来动态更改摘要。问题在于它获取了选定的值(从android:entryValues),而不是标题(android:entries)。在下面的代码中,我使用了toString(),但正确的解决方案是找到该值的标题。无论如何,这个想法是可行的:

public class Preferences extends PreferenceActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.your_prefs);

        ListPreference listPreference = (ListPreference) findPreference("preference_key");
        if(listPreference.getValue()==null) {
            // to ensure we don't get a null value
            // set first value by default
            listPreference.setValueIndex(0);
        }
        listPreference.setSummary(listPreference.getValue().toString());
        listPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                preference.setSummary(newValue.toString());
                return true;
            }
        });
    }
}

17

我也希望实现类似的功能,但是https://dev59.com/uW445IYBdhLWcg3wgqnT#8155029的问题在于它显示了我偏好的值(如1、2、3等),我要显示与所选值对应的条目(可读字符串)。

因此,我这样改变它,就可以按照我需要的方式工作。

listPreference.setSummary(servicePreference.getEntry().toString());
listPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            // Set the value as the new value
            listPreference.setValue(newValue.toString());
            // Get the entry which corresponds to the current value and set as summary
            preference.setSummary(listPreference.getEntry());
            return false;
        }
    });

诀窍在于使用getEntry()而不是getValue(),并且一旦更改了值,就要显式地设置该值并重新读取条目。


10
非常简单 - 只需将以下属性添加到您的XML定义中 -
<ListPreference
...    
app:useSimpleSummaryProvider="true"
...
/>

6
我认为这应该得到点赞,因为这似乎是优选方案而非 %s。至少根据我在 logcat 中收到的消息: "不再支持使用字符串格式标记设置摘要。您应该使用 SummaryProvider。" - Henrik

7

我觉得您要找的东西比您想象的要简单得多,只需将以下代码行添加到您的偏好设置项中:

android:summary="%1$s"

所以它将看起来像这样:
<ListPreference
            android:key="@string/pref_temp_key"
            android:title="@string/pref_temp_title"
            android:dialogTitle="@string/pref_temp_dialog_title"
            android:entries="@array/pref_tempUnit_entries"
            android:entryValues="@array/pref_tempUnit_entries"
            android:summary="%1$s"
            android:defaultValue="@string/pref_temp_default_value" />

3

首先,在onCreate中引用ListPreference。您可以使用findPreference()方法。例如:

ListPreference pref = (ListPreference) findPreference("thePreferencesKey");

接下来,当您首次加载Activity或者偏好设置值改变时,使用任何您想要的方法来获取ListPreference的值,并使用以下代码设置摘要:

pref.setSummary(theNewString);

2
这是我正在使用的代码,它不会手动调用setValue,因为我相信这已经在后面的阶段完成了。
以下是一个例子:
@Override
public boolean onPreferenceChange(Preference preference, Object value)
{
    String textValue = value.toString();

    ListPreference listPreference = (ListPreference) preference;
    int index = listPreference.findIndexOfValue(textValue);

    CharSequence[] entries = listPreference.getEntries();

    preference.setSummary(
                index >= 0
                        ? entries[index]
                        : null);

    return true;
}

0
这是midhunhk答案的扩展版本,还涉及到有用的“android:summary”字符串。
        // Retrieve & populate flash modes
        List<String> flashmodes = params.getSupportedFlashModes();
        if (flashmodes != null) {
            final ListPreference lp = (ListPreference) findPreference("flash_list");
            final String lp_basesummary = "Set the Flash mode. The default is 'auto'";

            lp.setEntries(flashmodes.toArray(new CharSequence[flashmodes.size()]));
            lp.setEntryValues(flashmodes.toArray(new CharSequence[flashmodes.size()]));
            // If there's only one option, make it the default
            if (flashmodes.size() == 1)
                lp.setValueIndex(0);

            lp.setSummary(lp_basesummary + " [" + lp.getEntry() + "]");

            lp.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

                @Override
                public boolean onPreferenceChange(Preference preference, Object newValue) {
                    // Set the value as the new value
                    lp.setValue(newValue.toString());
                    // Get the entry which corresponds to the current value
                    // and set as summary
                    preference.setSummary(lp_basesummary + " [" + lp.getEntry() + "]");
                    return false;
                }
            });
        } else {
            // Remove the preference
            ((PreferenceGroup) findPreference("camera_preference")).removePreference(findPreference("flash_list"));
        }

        // Retrieve & populate focus modes
        List<String> focusmodes = params.getSupportedFocusModes();
        if (focusmodes != null) {
            final ListPreference lp = (ListPreference) findPreference("focus_mode_list");
            final String lp_basesummary = "Set the Focus mode. The default is 'auto'";
...

而且,只是为了明确起见,android:summary已从相关的xml中删除。


0
这里有一种处理用户选择后铃声偏好摘要更新的方法。
    final SharedPreferences preference = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());

    final RingtonePreference rp_shuttle = (RingtonePreference) findPreference("shuttle_tone");
    rp_shuttle.setSummary(RingtoneManager
            .getRingtone(getApplicationContext(), Uri.parse(preference.getString("shuttle_tone", "DEFAULT_SOUND")))
            .getTitle(this));

    rp_shuttle.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

        public boolean onPreferenceChange(Preference mypreference, Object newValue) {
            rp_shuttle.setSummary(RingtoneManager.getRingtone(getApplicationContext(), Uri.parse(newValue + ""))
                    .getTitle(getApplicationContext()));

            return true;
        }
    })

0
你在PreferenceActivity中有一个名为bindPreferenceSummaryToValue的方法,你可以通过以下方式轻松地将摘要添加到列表中:
private static void bindPreferenceSummaryToValue(Preference preference) {
    preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);

    sBindPreferenceSummaryToValueListener.onPreferenceChange(preference,
            PreferenceManager
                    .getDefaultSharedPreferences(preference.getContext())
                    .getString(preference.getKey(), ""));
}

在你的OnCreate方法中,你可以这样调用bind函数:
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_OF_THE_LIST)));

您可以轻松地以同样的方式添加其他摘要:

bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_1)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_2)));
bindPreferenceSummaryToValue(findPreference(getString(R.string.KEY_3)));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接