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();
}
}
});
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();
}
});
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();
}
});
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);
})
});
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)
.
.
.
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;
}
});
来源:https://stackoverflow.com/questions/31640784/how-to-flip-the-checked-status-of-a-switch-only-after-confirm-dialog