Java Android-以编程方式更改开关的状态,而无需触发OnCheckChanged侦听器

Java Android-以编程方式更改开关的状态,而无需触发OnCheckChanged侦听器,java,android,onclicklistener,oncheckedchanged,android-switch,Java,Android,Onclicklistener,Oncheckedchanged,Android Switch,我正在寻找一种使用Switch.setChecked(true)以编程方式更改Android Switch小部件状态的方法不触发一次checkedChangedListener我的第一个想法是把它换成一个OnClickListener,但由于它只注册点击,而且你不仅可以点击,还可以滑动开关,所以它并不真正适合使用,就像用户要将开关从关闭滑动到打开一样,那么开关实际上不会起任何作用,因为用户没有点击…如果任何人都有一个解决方案或智能解决方案,这将是非常棒的好吧,在使用开关进行代码操作之前,您可以先


我正在寻找一种使用
Switch.setChecked(true)以编程方式更改Android Switch小部件状态的方法
不触发一次checkedChangedListener

我的第一个想法是把它换成一个
OnClickListener
,但由于它只注册点击,而且你不仅可以点击,还可以滑动开关,所以它并不真正适合使用,就像用户要将开关从关闭滑动到打开一样,那么开关实际上不会起任何作用,因为用户没有点击…

如果任何人都有一个解决方案或智能解决方案,这将是非常棒的

好吧,在使用开关进行代码操作之前,您可以先注销侦听器,然后执行您需要的任何操作,然后再次注册侦听器。

我有一个解决方案,它在我这边工作正常。 我在交换机控件上添加了setOnTouchListener和setOnCheckedChangeListener,并添加了以下代码来解决我的问题

    // 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;
         }
    });
通过这种方式,setOnCheckedChangeListener只有在通过拖动、单击或触摸进行人工干预时才会被调用

另外,在尝试更改开关控件的检查状态时,不要忘记添加有效的字符串标记(非null)。 比如:


在调用setCheck()函数之前,将侦听器设置为null,然后启用它,例如:

switch.setOnCheckedChangeListener (null);
switch.setChecked(true);
switch.setOnCheckedChangeListener (this);

参考资料

详细阐述马哈茂德的答案

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);
     }

`

编写一个自定义开关或SwitchCompat并覆盖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;
}

}
每个(两个状态按钮-开/关)都有一个按下状态,只有当用户按下视图时,该状态才为真

在启动实际逻辑之前,只需在侦听器中添加一个检查:

if(compoundButton.isPressed()) {
    // continue with your listener
}
这样,以编程方式更改选中值不会触发不需要的代码

从答案中。

使用此选项
switch.setChecked(true);//第一个设置值(来自pref或server或任意位置)并大于switch.setOnCheckedChangeListener(此)添加侦听器。

我能找到的最佳解决方案是

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
    }
}

如果这里什么都不起作用,这是一个棘手的解决办法

在交换机顶部创建一个textview,并将clickListener添加到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" />


将elavation添加到textview。

如何注销侦听器?对不起,我对这个很陌生。我想有两个选择:1。switch.setOnCheckedChangeListener(null)//不确定,但如果这会导致问题。。。2.创建一个虚拟类,用一个虚拟方法onCheckedChanged实现OnCheckedChangeListender,它什么也不做。然后注册一个新的对象,然后再次注册您的默认Listener,如果我要使用switch.setOnCheckedChangeListener(null);然后如何重新注册侦听器?它会是switch.setOnCheckedChangeListener(listener);??只要“listener”是对listener对象的引用,就可以。这将是我解决这个问题的方法(尽管我有更好的解决方案)。你是如何重新注册听众的?感谢这个解决方案,帮了我很多!!不需要mListener,遗憾的是没有switch.getOnCheckedChangeListener()方法。顺便说一句:在你的onCheckedChanged()中,可以用按钮替换mmy开关。查看工作情况非常好,亲切!请使用下面的代码行。“buttonView.isPressed()”很抱歉,这没有起作用,onCheckedChanged仍然被重复调用。这不能可靠地工作,因为对于与开关的刷卡交互而言,
isPressed
通常是错误的,而不是点击。
 <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" />