PreferenceFragment中的对话框生成器

时间:2014-12-31 10:48:47

标签: android dialog listpreference preferencefragment

我正在为我的应用创建设置部分。这将作为PreferenceFragment加载到导航抽屉布局中。

我有一个ListPreference,我将用它来切换应用主题。从列表视图中选择主题后,我会设置一个确认对话框,询问用户是否要重新启动应用程序以应用新主题。如果是,我使用以下命令重新启动在Utils.java中定义的应用程序:

public static void changeTheme(Activity activity, int theme)
{
    if (null != activity) {
        activity.finish();
        activity.startActivity(new Intent(activity, activity.getClass()));
    }
}

除1个问题外,这项工作非常完美。在用户更改了主题并且应用程序已重新启动后,如果用户在没有先手动退出并打开应用程序的情况下再次尝试选择新主题,则对AlertDialog.Builder的调用将失败,并且我不确定原因。我在logcat中得到了这个错误:

  

android.view.WindowManager $ BadTokenException:无法添加窗口 - 令牌android.os.BinderProxy@41eec418无效;你的活动在运行吗?

创建对话框时失败:

new AlertDialog.Builder(mContext)...

我在onCreate方法中设置了mContext = getActivity(),而对话框构建器的调用在onSharedPreferenceChanged中:

public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    Log.e(TAG, "Preference Change!");
    Log.e(TAG, "Key: " + key);

    if (preferenceManager.contains(key)) {
        if (key.equals(PrivateGalleryConstants.KEY_THEME)) {
            final int theme = Integer.parseInt(preferenceManager.getString(key, "0"));
            Log.e(TAG, "Value: " + preferenceManager.getString(key, "0"));

            new AlertDialog.Builder(mContext)
                    .setIcon(android.R.drawable.ic_dialog_alert)
                    .setTitle(R.string.confirm_restart_title)
                    .setMessage(R.string.confirm_restart_message)
                    .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            Utils.changeTheme(getActivity(), theme);
                        }

                    })
                    .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {

                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                        }

                    })
                    .show();


        }
        if (key.equals(PrivateGalleryConstants.KEY_ENABLE_SECURITY))
            Log.e(TAG, "Value: " + preferenceManager.getBoolean(key, false));
    }
}

我不明白为什么只有在应用程序自行重启后,对AlertDialog.Builder的调用才会失败(如果您手动关闭应用程序然后再次打开它,则不会发生这种情况)。任何想法如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

所以我决定实现一个扩展的ListPreference来处理创建确认对话框的问题,现在它完美无缺。

public class ThemeListPreference extends ListPreference {

    private int mClickedDialogEntryIndex;

    private Context mContext;

    public ThemeListPreference(Context ctxt) {
        this(ctxt, null);
    }

    public ThemeListPreference(Context ctxt, AttributeSet attrs) {
        super(ctxt, attrs);

        mContext = ctxt;

        setNegativeButtonText(ctxt.getString(R.string.no));
    }

    @Override
    protected void onPrepareDialogBuilder(Builder builder) {
        if (getEntries() == null || getEntries() == null) {
            throw new IllegalStateException(
                    "ListPreference requires an entries array and an entryValues array.");
        }

        mClickedDialogEntryIndex = findIndexOfValue(getValue());
        builder.setSingleChoiceItems(getEntries(), mClickedDialogEntryIndex,
                new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, final int which) {
                        // Save preference and close dialog
                        mClickedDialogEntryIndex = which;

                        ThemeListPreference.this.onClick(dialog, DialogInterface.BUTTON_POSITIVE);
                        dialog.dismiss();

                        new AlertDialog.Builder(mContext)
                                .setIcon(android.R.drawable.ic_dialog_alert)
                                .setTitle(R.string.confirm_restart_title)
                                .setMessage(R.string.confirm_restart_message)
                                .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {

                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        dialog.dismiss();
                                        Utils.changeTheme((Activity) mContext);
                                    }

                                })
                                .setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {

                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        dialog.dismiss();
                                    }

                                })
                                .show();
                    }
                });

        builder.setPositiveButton(null, null);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {

        CharSequence[] mEntryValues = getEntryValues();

        if (positiveResult && mClickedDialogEntryIndex >= 0 && mEntryValues != null) {
            String value = mEntryValues[mClickedDialogEntryIndex].toString();
            if (callChangeListener(value)) {
                setValue(value);
            }
        }
    }
}

希望将来可以帮助其他人; - )