通过代码修改 PreferenceScreen 中的首选项值

Modifying a preference value in a PreferenceScreen by code

我有一个遵循文档 here and here 的 PreferenceScreen。

其中一个选项是 SwitchPreferenceCompat,它在我的应用程序中执行一些有风险的工作,例如,定期发送敏感信息。这是简单的开关:

<SwitchPreferenceCompat
            app:key="SendInfoToServer"
            app:title="Send information on your device to our servers" />

我需要的是向用户提出这样的问题:

This will periodically send sensitive information of your device to our servers. Are you sure you want to enable this option?

如果用户回答是,那么我希望激活 SwitchPreferenceCompat,否则不激活。

我调查了一下,发现这段代码:

    findPreference("SendInfoToServer").setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            if((boolean) newValue == true){
                Toast("Activating this function will safe sensitive information");
            }
            return true;
        }
    });

但此消息只是向用户显示的警告消息。我想要实现的是提出一个问题。如果用户同意则开关应打开,如果用户不同意则开关应保持关闭。

关于如何做到这一点的任何想法。

您可以使用isChecked方法修改它。这是一个使用您描述的弹出对话框执行此操作的示例。这使用 onPreferenceChangeListener,如果该选项被禁用,它会显示一个对话框,并且 returns false 用于侦听器(因此首选项不会立即更新)。

如果用户在对话框中选择了正确的选项,则会使用 isChecked 方法将其禁用。如果重新启用该选项,则不会显示该对话框,只有当它被禁用时才会显示。

如果您想在启用该选项时显示对话框,则某些逻辑可能会颠倒,但总体概念是相同的。关键是在显示对话框时将 return false 设置为 false,这样它就不会更改,如果用户确认他们想要更改它,则稍后使用 isChecked 更改它。

// replace this with getting the switch if you defined it in the XML
val enableChecks = SwitchPreference(context)
enableChecks.key = Constants.ENABLE_CHECKS
enableChecks.title = getString(R.string.enable_checks)
enableChecks.isPersistent = true


enableChecks.onPreferenceChangeListener =
    Preference.OnPreferenceChangeListener { _, value ->

        val disabling = !(value as Boolean)
        if( disabling ) {
            SimpleDialogs.twoButton(
                context,
                title = getString(R.string.confirm_disable_check),
                message = getString(R.string.confirm_disable_check_msg),
                posButton = getString(R.string.disable),
                negButton = getString(R.string.cancel),
                onPos = {
                    // user confirmed they want to disable it, set to false
                    enableChecks.isChecked = false
                },
                onNeg = {
                    // user changed their mind, keep it true
                    enableChecks.isChecked = true
                },
                icon = SimpleDialogs.ICON_WARNING
            )

            // return false so the change isn't applied here if showing a dialog
            false
        }
        else {
            true
        }
    }

appearanceCat.addPreference(enableChecks)

Java 中的类似答案基于 Tyler V 答案:

    SwitchPreferenceCompat oSwitchPreferenceCompat = findPreference("MyKey");
    oSwitchPreferenceCompat.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            if((boolean) newValue == false){
                return true; //If the check is disabled we do not need to ask the user. In this case we allow the normal flow and let the system disable it. Returning "true" allows the System to disable it.
            }
            //Here the user is enabling the check, so we prompt to confirm it:
            AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
            builder.setMessage("Are you sure you want to enable this?");
            builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    oSwitchPreferenceCompat.setChecked(true);
                }
            });
            builder.setNegativeButton("No", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int which) {
                    oSwitchPreferenceCompat.setChecked(false);
                }
            });
            builder.setCancelable(false);
            Dialog d = builder.create();
            d.show();
            return false;//returning false we are telling the System to not modify the check yet.
        }
    });