android - 如何在用户更改 ListPreference 值之前在 SettingsFragment 中显示确认消息?

标签 android android-fragments android-preferences listpreference

我的 SettingsFragment 中有一个 ListPreference,我想在用户使用确认按钮更改值时显示一条警告消息。只有用户确认,ListPreference 值才会真正更改为选择。我该怎么做?

最佳答案

这是一个较旧的问题,但这里有一个答案,以防其他人需要它。首先是解释,最后是工作代码。

如果我没理解错的话,您需要添加一个肯定按钮(例如“确定”或"is"),它实际上会进行更改,而不是在单击列表项时立即进行更改。像这样:

Example using the code below


解释

ListPreference 覆盖 onPrepareDialogBu​​ilder(Builder builder) 中列表项的 onClick 方法,因此:

Clicking on an item simulates the positive button click, and dismisses the dialog.

它还以相同的方法覆盖肯定按钮的监听器(即删除它),解释如下:

The typical interaction for list-based dialogs is to have click-on-an-item dismiss the dialog instead of the user having to press 'Ok'.

您需要再次覆盖它,但没有该功能。这是执行此操作的代码 fragment (在 onPrepareDialogBu​​ilder(Builder builder) 内),您想摆脱:

builder.setSingleChoiceItems(mEntries, mClickedDialogEntryIndex, 
        new DialogInterface.OnClickListener()
        {
            public void onClick(DialogInterface dialog, int which)
            {
                mClickedDialogEntryIndex = which;

                /* Clicking on an item simulates the positive button
                 * click, and dismisses the dialog. */
                ListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE); // <--- don't want this
                dialog.dismiss(); // <--- don't want this
            }
        }
);

builder.setPositiveButton(null, null); // <--- don't want this

您还需要在单击肯定按钮后应用更改,这是在 onDialogClosed(boolean positiveResult) 中完成的。

因此您需要创建一个自定义类来扩展 ListPreference 并覆盖 onPrepareDialogBu​​ilder(Builder builder)onDialogClosed(boolean positiveResult)


代码

这是我使用的 ConfirmationListPreference 示例:

package com.your.pckg;

import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Build;
import android.preference.ListPreference;
import android.util.AttributeSet;

public class ConfirmationListPreference extends ListPreference
{
    /** Holds the index of the selected item. */
    private int mClickedDialogEntryIndex;

    // Constructors; these are standard and required for the subclass
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public ConfirmationListPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
    {
        super(context, attrs, defStyleAttr, defStyleRes);
    }
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public ConfirmationListPreference(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }
    public ConfirmationListPreference(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }
    public ConfirmationListPreference(Context context)
    {
        super(context);
    }

    @Override
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder)
    {
        // not calling the super method (the one from ListPreference), since
        // that's the one that disables the positive button functionality,
        // but we'll use most of its code, all except the parts we don't want

        if (getEntries() == null || getEntryValues() == null)
        {
            throw new IllegalStateException("ConfirmationListPreference requires an entries array and an entryValues array.");
        }

        // get the index of the selected item
        mClickedDialogEntryIndex = findIndexOfValue(this.getValue());

        builder.setSingleChoiceItems(getEntries(), mClickedDialogEntryIndex,
                new DialogInterface.OnClickListener()
                {
                    public void onClick(DialogInterface dialog, int which)
                    {
                        // update the index of the selected (clicked) item
                        mClickedDialogEntryIndex = which;

                        // the stuff we don't want is removed
                        // ...
                    }
                }
        );

        // and don't set the positive button listener to null
        // ...
    }

    @Override
    protected void onDialogClosed(boolean positiveResult)
    {
        // we can't use the super method because mClickedDialogEntryIndex
        // is private and there's no setter, so we'll just copy its code

        if (positiveResult && mClickedDialogEntryIndex >= 0 && getEntryValues() != null)
        {
            String value = getEntryValues()[mClickedDialogEntryIndex].toString();

            if (callChangeListener(value))
            {
                setValue(value);
            }
        }
    }
}

然后在您的首选项 xml 中使用它(例如 pref_general.xml),如下所示:

<com.your.pckg.ConfirmationListPreference
    android:key="@string/key_pref_app_language"
    android:title="@string/pref_app_language_title"
    android:entries="@array/pref_app_language_list_titles"
    android:entryValues="@array/pref_app_language_list_values"
    android:defaultValue="0"
    android:negativeButtonText="@string/button_title_cancel"
    android:positiveButtonText="@string/button_title_ok"
    />

关于android - 如何在用户更改 ListPreference 值之前在 SettingsFragment 中显示确认消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44989083/

相关文章:

Android 将数据从 Activity 传递到 BroadcastReceiver 显示 null

Android 屏幕方向行为

java - 我的自定义 Activity 中的谷歌地图

android - 无法访问类型 MainActivity 的封闭实例?

android - 通过 Assets 字体更改 PreferenceFragment 字体

android - 如何更改支持包的首选项对话框颜色?

android - 如何监听 PreferenceFragment 中的偏好变化?

android - 如何检测使用STREAM_VOICE_CALL或Android中的音频扬声器?

android - TabFragment 中的 ViewPager 未再次加载

android - 在谷歌地图上绘制路线