83

我在 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"/>
4

10 回答 10

269

奇怪的是我们所有人都有这个问题,但谷歌没有对这个简单问题的官方回答。

最简单的检查是:

buttonView.isPressed()

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

不需要全局变量。

于 2015-01-29T16:13:51.897 回答
14

我最终使用了 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方法中设置并且您将返回到前一个片段时,也触发了监听。希望这对你有用!

于 2016-05-30T23:27:44.097 回答
13

尝试这个

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

        if (buttonView.isPressed()) {
          ... //returns true, if user clicks the switch button        
        }}
于 2018-06-28T13:40:18.600 回答
6

由于RecyclerView是回收视图,因此在为新项目OnCheckedChangeListener设置检查值时可以触发先前附加的。Switch

将新数据绑定到项目时:

   switch.setOnCheckedChangeListener(null) // remove any existing listener from recycled view
   switch.isChecked = [true/false] // will no longer trigger any callback to listener
   switch.setOnCheckedChangeListener { btnView, isChecked ->
       // do exiting stuff
   }
于 2021-01-15T19:57:03.783 回答
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);
                    }
                }
            });
于 2018-04-05T15:29:00.663 回答
0

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

@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
于 2014-12-24T20:53:14.547 回答
0

我在 ViewPager 屏幕的片段中遇到了同样的问题。当我们在片段之间切换时,会一次又一次地调用 onCheckedChanged 监听器。

如果有人还在寻找这个问题,请尝试一下。

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

            if (buttonView.isInTouchMode()) {
              ... //Your code will come here.         
            }
}
于 2015-04-09T10:47:58.607 回答
0

Kotlin 开发人员:

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

        }
    }
于 2020-08-14T15:11:27.320 回答
0

如果您正在更改适配器中的状态,那么

   holder.rawManageDriverLayoutBinding.rawManageDriverSwitch.setOnCheckedChangeListener(null);

之前setOnCheckedChangeListener

于 2021-10-25T11:18:04.703 回答
-1

唯一的解决方案是在侦听器中使用方法 isPressed()

于 2022-01-01T18:43:18.283 回答