How to flip the checked status of a Switch only af

2019-05-19 01:59发布

问题:

My problem is - when I click on a <Switch>, it gets toggled first and then the OnCheckedChangeListener is called.

What I would like is this:

<Switch> is clicked --> I show an AlertDialog --> If pressed yes or no --> Then flip ` with setChecked(boolean), [boolean = true if pressed yes, and false if pressed no].

Problem: When <Switch> is clicked, it gets flipped automatically. I want to qualify it with a yes or no from a AlertDialog first.

sw_enableDisable
                .setOnCheckedChangeListener(new OnCheckedChangeListener() {

                    @Override
                    public void onCheckedChanged(CompoundButton buttonView,
                                                 boolean isChecked) {
                        if (isChecked) {

                            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                                    getActivity());

                            alertDialogBuilder
                                    .setMessage(
                                            "Sure you want to enable?. ")
                                    .setCancelable(true)
                                    .setPositiveButton(
                                            getString("YES"),
                                            new DialogInterface.OnClickListener() {
                                                @Override
                                                public void onClick(DialogInterface dialog,
                                                                    int which) {

                                                    dialog.cancel();
                                                }
                                            })

                                    .setNegativeButton(
                                            getString("NO"),
                                            new DialogInterface.OnClickListener() {

                                                @Override
                                                public void onClick(DialogInterface dialog,
                                                                    int which) {

                                                    dialog.cancel();
                                                }
                                            });

                            AlertDialog alertDialog = alertDialogBuilder.create();
                            alertDialog.show();
                            sw_enDis_alreadyClicked = true;

                        } else {
                            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                                    getActivity());
                            alertDialogBuilder
                                    .setMessage(
                                            "Sure you want to disable?")
                                    .setCancelable(true)
                                    .setPositiveButton(
                                            getString("YES"),
                                            new DialogInterface.OnClickListener() {
                                                @Override
                                                public void onClick(DialogInterface dialog,
                                                                    int which) {
                                                    dialog.cancel();
                                                }
                                            })

                                    .setNegativeButton(
                                            getString("NO"),
                                            new DialogInterface.OnClickListener() {

                                                @Override
                                                public void onClick(DialogInterface dialog,
                                                                    int which) {

                                                    dialog.cancel();
                                                }
                                            });

                            AlertDialog alertDialog = alertDialogBuilder.create();
                            alertDialog.show();
                        }
                    }
                });

回答1:

Try this code. It worked for me:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...
    Switch switchButton = (Switch) findViewById(R.id.my_switch_id);

    switchButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            final Switch btn = (Switch) v;
            final boolean switchChecked = btn.isChecked();

            if (btn.isChecked()) {
                btn.setChecked(false);
            } else {
                btn.setChecked(true);
            }

            String message = "Are you sure you want to disable this setting?";
            if (!btn.isChecked()) {
                message = "Are you sure you want to enable this setting?";
            }
            AlertDialog.Builder builder = new AlertDialog.Builder(this); // Change "this" to `getActivity()` if you're using this on a fragment
            builder.setMessage(message)
                   .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int i) {
                            // "Yes" button was clicked
                            if (switchChecked) {
                                btn.setChecked(true);
                            } else {
                                btn.setChecked(false);
                            }
                        }
                    })
                   .setNegativeButton("Cancel", null)
                   .show();
        }
    });


回答2:

Try to use onClick:

switch.setOnClickListener(new OnCLickListener(){
    Here_is_createing_of_dialog...
    dialogBuilder.setPositiveButton(
    getString("YES"),
    new DialogInterface.OnClickListener() { 
    @Override
    public void onClick(DialogInterface dialog, int which) {
        dialog.cancel();
        switch.setChecked(true);
    })
});


回答3:

Use the following updated code.

sw_enableDisable
                .setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

                    @Override
                    public void onCheckedChanged(CompoundButton buttonView,
                                                 boolean isChecked) {
                        if (toogledProgrammatically) {
                            toogledProgrammatically = false;
                        } else {
                            if (isChecked) {

                                AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                                        MainActivity.this);

                                alertDialogBuilder
                                        .setMessage(
                                                "Sure you want to enable?. ")
                                        .setCancelable(true)
                                        .setPositiveButton(
                                                "YES",
                                                new DialogInterface.OnClickListener() {
                                                    @Override
                                                    public void onClick(DialogInterface dialog,
                                                                        int which) {

                                                        dialog.cancel();
                                                    }
                                                })

                                        .setNegativeButton(
                                                "NO",
                                                new DialogInterface.OnClickListener() {

                                                    @Override
                                                    public void onClick(DialogInterface dialog,
                                                                        int which) {

                                                        dialog.cancel();
                                                        toogledProgrammatically = true;
                                                        sw_enableDisable.toggle();
                                                    }
                                                });

                                AlertDialog alertDialog = alertDialogBuilder.create();
                                alertDialog.show();
                            } else {
                                AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                                        MainActivity.this);
                                alertDialogBuilder
                                        .setMessage(
                                                "Sure you want to disable?")
                                        .setCancelable(true)
                                        .setPositiveButton(
                                                "YES",
                                                new DialogInterface.OnClickListener() {
                                                    @Override
                                                    public void onClick(DialogInterface dialog,
                                                                        int which) {
                                                        dialog.cancel();
                                                    }
                                                })

                                        .setNegativeButton(
                                                "NO",
                                                new DialogInterface.OnClickListener() {

                                                    @Override
                                                    public void onClick(DialogInterface dialog,
                                                                        int which) {

                                                        dialog.cancel();
                                                        toogledProgrammatically = true;
                                                        sw_enableDisable.toggle();
                                                    }
                                                });

                                AlertDialog alertDialog = alertDialogBuilder.create();
                                alertDialog.show();
                            }
                        }
                    }
                });

So whenever the user clicks on No of the AlertDialog, you're supposed to toggle the switch again by using

sw_enableDisable.toggle();

But this would in turn call onCheckedChanged() and then it'd be cycle all over again. So to handle that, maintain a boolean toogledProgrammatically and set it to true whenever you're toggling it in the code. And then when the onCheckedChanged() is called, just check if it was toggled programmatically or not. If yes, then don't do anything, else show the alert.

if (toogledProgrammatically) {
                            toogledProgrammatically = false;
                        } else {
                            if (isChecked)
.
.
.


回答4:

prevent switching by setting back state.

    Switch switchButton=(Switch)rootView.findViewById(R.id.switch_id);


    switchButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            final Switch btn=(Switch)v;
            final boolean estado=btn.isChecked();

            if(btn.isChecked())btn.setChecked(false);
            else btn.setChecked(true);


            DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    switch (which){
                    case DialogInterface.BUTTON_POSITIVE:
                        if(estado)btn.setChecked(true);
                        else btn.setChecked(false);
                        break;

                    case DialogInterface.BUTTON_NEGATIVE:
                        //No button clicked
                        break;
                    }
                }
            };

            String message="Disable function?";
            if(!btn.isChecked()) message="Enable function?";

            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
            builder.setMessage(message).setPositiveButton("YES", dialogClickListener)
                .setNegativeButton("NO", dialogClickListener).show();


        }
    });


回答5:

Intercepting touch event will solve the problem. Return TRUE if don't want to send event forward to the system. I came up with below approach. Have tested, working as expected.

switchButton.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            switch (motionEvent.getAction()) {
                case ACTION_DOWN:
                    if (!switchButton.isChecked()) {
                        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
                                ActivityLogin.this);

                        alertDialogBuilder
                                .setMessage(
                                        "Sure you want to enable?. ")
                                .setCancelable(true)
                                .setPositiveButton("YES",
                                        new DialogInterface.OnClickListener() {
                                            @Override
                                            public void onClick(DialogInterface dialog,
                                                                int which) {
                                                dialog.cancel();
                                                switchButton.performClick();
                                            }
                                        })

                                .setNegativeButton(
                                        "NO",
                                        new DialogInterface.OnClickListener() {

                                            @Override
                                            public void onClick(DialogInterface dialog,
                                                                int which) {

                                                dialog.cancel();
                                            }
                                        });

                        AlertDialog alertDialog = alertDialogBuilder.create();
                        alertDialog.show();
                        return true;
                    } else{
                        // show dialog Sure you want to disable? and handle the button events accordingly
                    }
            }
            return false;
        }
    });