I'm looking for a method of programmatically changing the state of an Android Switch widget using switch.setChecked(true);
without triggering OnCheckedChangedlistener
.
My first thought was to swap it out for an OnClickListener
but as this only registers clicks and you are able to not only click but also slide a Switch then it's not really fit for purpose as if the user was to slide the Switch from off to on then the Switch would actually do nothing as the user is not clicking...
If anyone's got a solution or a smart work around for this, that would be awesome

- 2,686
- 4
- 33
- 69
-
2Please use below line of code. "buttonView.isPressed()" – Mandeep Yadav Mar 05 '19 at 10:21
12 Answers
Set the listener to null before calling setCheck() function, and enable it after that, such as the following:
switch.setOnCheckedChangeListener (null);
switch.setChecked(true);
switch.setOnCheckedChangeListener (this);
Reference: Change Checkbox value without triggering onCheckChanged

- 1,057
- 11
- 20
-
Sorry but this didn't work out, onCheckedChanged was still repeatedly called. – iCantC Apr 16 '20 at 11:58
Every CompoundButton (two states button - on/off) has a pressed state which is true only when a user is pressing the view.
Just add a check in your listener before starting the actual logic:
if(compoundButton.isPressed()) {
// continue with your listener
}
That way, changing the checked value programmatically won't trigger the unwanted code.
From @krisDrOid answer.
-
2This doesn't work reliably as `isPressed` will often be false for a swipe interaction with the switch, as opposed to a tap. – Roman Kotenko Feb 11 '21 at 00:49
Well, just before doing things in code with the switch you could just unregister the Listener, then do whatever you need to, and again register the listener.

- 589
- 5
- 6
-
How would you go about unregistering the listener? sorry, i'm quite new to this – Paul Alexander Sep 03 '14 at 10:41
-
2I think there are two options: 1. switch.setOnCheckedChangeListener(null); //not sure though, if that could lead to problems... 2. create a dummy class, implementing the OnCheckedChangeListender with a dummy method onCheckedChanged, which does nothing. then registering a new object of that and later on again registering you default listener – smnpl Sep 03 '14 at 10:44
-
so if I was to use switch.setOnCheckedChangeListener(null); how would I then re-register the listener? would it be switch.setOnCheckedChangeListener(listener);?? – Paul Alexander Sep 03 '14 at 11:09
-
2As long as 'listener' is a reference to your listener object, yes. That would have been my approach to work this around (though there my be better solutions). – smnpl Sep 03 '14 at 12:00
-
hmm I can't seem to get the re-register to work... I'm not sure what I'm supposed to be putting in the brackets of switch.setOnCheckedChangeListener(); – Paul Alexander Sep 03 '14 at 12:03
-
-
3
I have one solution and its working fine at my end. I have added setOnTouchListener and setOnCheckedChangeListener on my switch control, and added following code to solve my problem.
// set tag by default.
mMySwitch.setTag("TAG");
// Add OnCheckedChangeListener.
mMySwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mMySwitch.getTag() != null) {
mMySwitch.setTag(null);
return;
}
// Do your stuff here.
}
});
// Add Touch listener.
mMySwitch.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mMySwitch.setTag(null);
return false;
}
});
In this way setOnCheckedChangeListener is getting called only when check changed happens by human intervention by drag, by click, by touch.
Also don't forgot to add your valid string tag ( not null ) when your trying to change check status of switch control. like :
mMySwitch.setTag("TAG");
mMySwitch.setChecked(true);

- 501
- 4
- 12
-
Thanks for this solution, helped me a lot!! no need of mListener, unfortunately there is no switch.getOnCheckedChangeListener() method. BTW: in your onCheckedChanged() it is possible to replace mMySwitch with buttonView – Lucker10 Jul 23 '16 at 19:55
Write a custom Switch or SwitchCompat and override the setOnCheckedListener.
public class SwitchCompat extends android.support.v7.widget.SwitchCompat {
private boolean mIgnoreCheckedChange = false;
public SwitchCompat(Context context) {
super(context);
}
public SwitchCompat(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwitchCompat(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void setOnCheckedChangeListener(final OnCheckedChangeListener listener) {
super.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mIgnoreCheckedChange) {
return;
}
listener.onCheckedChanged(buttonView, isChecked);
}
});
}
public void setChecked(boolean checked, boolean notify) {
mIgnoreCheckedChange = !notify;
setChecked(checked);
mIgnoreCheckedChange = false;
}
}

- 147
- 3
- 10
the best solution I can find is;
const val SWITCH_COMPAT_IGNORE_TAG = "SWITCH_COMPAT_IGNORE_TAG"
fun SwitchCompat.isCheckedWithIgnoreTag(isChecked: Boolean) {
tag = SWITCH_COMPAT_IGNORE_TAG
this.isChecked = isChecked
tag = null
}
switchCompat.isCheckedWithIgnoreTag(true)
switchCompat.setOnCheckedChangeListener { buttonView, isChecked ->
if (buttonView.tag != SWITCH_COMPAT_IGNORE_TAG) {
//TODO
}
}

- 1,640
- 1
- 13
- 17
Based on the answers from @ronginat and @hyb1996 I made SensibleSwitch
so that you can just drop it in your XML layouts, use the listener as you would expect to and not worry about it.
import android.content.Context
import android.util.AttributeSet
import androidx.appcompat.widget.SwitchCompat
class SensibleSwitch : SwitchCompat {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun setOnCheckedChangeListener(listener: OnCheckedChangeListener?) {
super.setOnCheckedChangeListener { compoundButton, isChecked ->
if (isPressed) {
listener?.onCheckedChanged(compoundButton, isChecked)
}
}
}
}

- 236
- 1
- 8
switch.setOnCheckedChangeListener
{
compoundButton, check
if (switch.isPressed || switch.isSelected)
if (check) {
TODO("")
} else {
TODO("")
}
}

- 69
- 3
-
2Please don't post code-only answers. The main audience, future readers, will be grateful to see explained *why* this answers the question instead of having to infer it from the code. Also, since this is an old question, please explain how it complements all other answers. – Gert Arnold Sep 19 '22 at 18:52
-
he is literally asking "without triggering OnCheckedChangedlistener" – Daniel Cettour Aug 25 '23 at 18:23
Elaborating on Mahmoud's answer
CompoundButton.OnCheckedChangeListener switchListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
switchListener = new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
//Implement on check change
}
};
switch.setOnCheckedChangeListener (switchListener);
//When you want to trigger the checked of switch do the following
switch.setOnCheckedChangeListener (null);
switch.setChecked(true);
switch.setOnCheckedChangeListener (switchListener);
}
`

- 2,774
- 1
- 25
- 46
use this
switch.setChecked(true); // first set value (from pref or server or anywhere) and than switch.setOnCheckedChangeListener (this);
add listener.

- 108
- 8
If nothing worked here is a tricky solution.
Create a textview on top of the switch and add clickListener to textview.
<TextView
android:elevation="1dp"
android:id="@+id/switchLabel"
android:layout_width="0dp"
android:layout_height="0dp"
android:text=""
app:layout_constraintBottom_toBottomOf="@id/switch1"
app:layout_constraintStart_toStartOf="@+id/switch1"
app:layout_constraintTop_toTopOf="@id/switch1"
app:layout_constraintEnd_toEndOf="@id/switch1" />
Add elavation to textview.

- 1,177
- 3
- 13
- 35
For the default switch writed <Switch/>
on xml,
do this in kotlin to set it programmatically :
mySwitch.isChecked = true
Then, if you want to do some action when user click on it:
mySwitch.setOnCheckedChangeListener { compoundButton, isChecked ->
when (isChecked) {
true -> { /* do something here*/ }
false -> { /* do something here*/ }
}
}

- 326
- 3
- 8