onCheckedChanged自动调用


75

我从recyclerview中有一个开关,并且从DB检索数据后数据显示在recyclerview中。打开recyclerview时,我读取了DB,并且如果DB中的字段为“ Y”,则启用该开关,否则将禁用该开关。现在问题随之而来,也调用了onCheckedchanged侦听器,我希望仅当用户手动设置开关时才调用onCheckedChanged。

在打开下面的recyclerview时执行:

holder.enabledisable.setChecked(messengerRecord.get_is_valid().equalsIgnoreCase("Y"));

ViewHolder类:

public class viewHolder extends RecyclerView.ViewHolder implements CompoundButton.OnCheckedChangeListener{
public SwitchCompat enabledisable;
 public viewHolder(View v) {
            enabledisable = (SwitchCompat) v.findViewById(R.id.enabledisable);
            enabledisable.setOnCheckedChangeListener(this);
...................................
...................................

刚打开recyclerView时调用的OncheckedChanged方法:

@Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            Log.v("ranjith","called oncheckedchanged");
            MessengerRecord rec;
            rec = dbHelper.getRecord(descview.getText().toString());
            switch (buttonView.getId()) {
                case R.id.enabledisable:
                    if (isChecked) {
                        rec.set_is_valid("Y");
                        dbHelper.updateRecord(rec);
                     }
}

在布局文件中:

<android.support.v7.widget.SwitchCompat
    android:layout_marginRight="16dp"
    android:layout_marginEnd="16dp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:focusable="false"
    android:id="@+id/enabledisable"
    android:layout_alignRight="@+id/textview_to"
    android:layout_alignEnd="@+id/textview_to"
    android:layout_alignParentRight="true"
    android:layout_alignParentEnd="true"/>

Answers:


252

我们所有人都遇到这个问题很奇怪,但Google并未对此简单问题提供正式答案。

最简单的方法是检查:

buttonView.isPressed()

如果为true,则表示用户单击了视图。

无需全局变量。

希望这可以帮助。


4
这肯定是有效的。但是,如果用户滑动开关会发生任何事件吗?在这种情况下,如果使用者滑动了开关,则该开关不起作用。
2015年

感谢您提供这个简单而出色的解决方案。这也可以使用RadioButton。因为RadioGroup,我已经写了这个答案
苏菲安

感谢@Surfian的提及:),我很高兴这也适用于RadioButton
Sulfkain

16
如果您快速滑动“开关”,该解决方案将不起作用。愚蠢的谷歌
大椿

您可以通过实现OnClickListener并使用SwitchCompat的isChecked()方法进行检查来手动处理,而无需使用onCheckedChangeListener。
mr.boyfox

13

我最终使用了SwitchCompat的此子类来避免此问题。这样,我在使用此类的地方就不需要样板代码。每当您需要在不触发监听器的情况下更改选中的内容时,请使用setCheckedSilent代替setChecked

import android.content.Context;
import android.os.Parcelable;
import android.support.v7.widget.SwitchCompat;
import android.util.AttributeSet;

/**
 * Created by emanuel on 30/5/16.
 */
public class Switch extends SwitchCompat {

    private OnCheckedChangeListener listener;

    public Switch(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
        this.listener = listener;
        super.setOnCheckedChangeListener(listener);
    }

    @Override
    public void onRestoreInstanceState(Parcelable state) {
        super.setOnCheckedChangeListener(null);
        super.onRestoreInstanceState(state);
        super.setOnCheckedChangeListener(listener);
    }

    public void setCheckedSilent(boolean checked) {
        super.setOnCheckedChangeListener(null);
        super.setChecked(checked);
        super.setOnCheckedChangeListener(listener);
    }
}

onRestoreInstanceState当在onViewCreated方法中设置时,还触发了监听,并且您将返回上一个片段。希望对你有帮助!


11

尝试这个

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

        if (buttonView.isPressed()) {
          ... //returns true, if user clicks the switch button        
        }}

1
如果快速完成滑动,此操作将无效。
曼努埃尔

2

这对我有用:

 boolean selected = preferences.isChecked();
        yourCheckBox.setOnCheckedChangeListener(new 
            CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, 
            boolean isChecked) {
                    if (buttonView.isPressed()) {
               preferences.setChecked(isChecked);
                    } else {
                        yourCheckBox.setChecked(selected);
                    }
                }
            });

如果快速完成滑动,此操作将无效。
曼努埃尔

0

使用全局布尔变量,并在从数据库读取数据时将其设置为“ true”,并在onCheckChange中的check(if)之后再次将其设置为“ false”。在onCheckChange方法的第一个中,检查此变量是否为false执行代码,否则返回(此变量的默认值必须为false);

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

       Log.v("ranjith","called oncheckedchanged");
        MessengerRecord rec;
        rec = dbHelper.getRecord(descview.getText().toString());
        switch (buttonView.getId()) {
            case R.id.enabledisable:
                if (isChecked) {
                    rec.set_is_valid("Y");
                    dbHelper.updateRecord(rec);

          }
    }//end if
  isSourceDB = false; }// end oncheckedchange

这似乎是一种解决方法。我一直在寻找android中的一种功能,该功能仅在用户单击时才调用oncheckedchanged(即,焦点不再显示)。但这有效。由我投票。
Psypher 2014年

@Ranjith:当“切换”单击时,首先调用toggle()方法,并在切换方法中调用setchecked()方法。因此,您应该在切换方法中插入以上代码,而不要进行选中更改。顺便说一句,如果您只想编写onCheckChange(),则应编写一个仅更改switch的GUI状态并在从DB读取数据时调用它的方法。
mk72 2014年

0

我在ViewPager屏幕中遇到片段时遇到了相同的问题。当我们在片段之间切换时,onCheckedChanged Listener会被反复调用。

如果仍然有人在寻找此问题,请尝试。

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

            if (buttonView.isInTouchMode()) {
              ... //Your code will come here.         
            }
}

0

Kotlin开发人员:

    checkboxXYZ.setOnCheckedChangeListener { btnView, isChecked ->
        if (btnView.isPressed) {

        }
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.