2013-03-20 52 views

回答

193

不,你不能这样做。 onCheckedChanged方法直接从setChecked调用。你可以做的是:

mCheck.setOnCheckedChangeListener (null); 
mCheck.setChecked (false); 
mCheck.setOnCheckedChangeListener (mListener); 

source of CheckBox,和setChecked实施:

public void setChecked(boolean checked) { 
    if (mChecked != checked) { 
     mChecked = checked; 
     refreshDrawableState(); 

     // Avoid infinite recursions if setChecked() is called from a listener 
     if (mBroadcasting) { 
      return; 
     } 

     mBroadcasting = true; 
     if (mOnCheckedChangeListener != null) { 
      mOnCheckedChangeListener.onCheckedChanged(this, mChecked); 
     } 

     if (mOnCheckedChangeWidgetListener != null) { 
      mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked); 
     } 

     mBroadcasting = false;    
    } 
} 
+4

你打算如何让'mListener'? 'Checkbox'没有getCheckChangeListener的吸气剂 – tir38 2014-07-08 19:56:18

+10

好吧,不需要简单地downvote,因为你不明白解决方案。 'mListener'是由程序员创建的'OnCheckChangedListener'接口的一个实现。我的答案意味着程序员保留了对**自己的实现** - 'mListener'的引用。 – Shade 2014-07-09 08:20:52

+0

如果您想重复使用setChecked()方法,更改侦听器会是低效的吗? – Ren 2016-04-22 22:01:20

0

我猜使用反射是唯一的出路。事情是这样的:

CheckBox cb = (CheckBox) findViewById(R.id.checkBox1); 
try { 
    Field field = CompoundButton.class.getDeclaredField("mChecked"); 
    field.setAccessible(true); 
    field.set(cb, cb.isChecked()); 
    cb.refreshDrawableState(); 
    cb.invalidate(); 
} catch (Exception e) { 
    e.printStackTrace(); 
} 
+0

可能的工作,直到开发者修改字段名或者,例如,拉起“器isChecked”方法,层次......或做其他重构...... 至少添加像'如果(Build.VERSION.SDK_INT <= Build.VERSION_CODES .JELLY_BEAN){/ * do reflection * /}' – aeracode 2015-02-12 13:44:41

+0

鼓励打破API并深入内部是错误的想法。对实现的任何更改都会导致应用程序失败。 – mspanc 2015-10-28 17:49:33

8
你用简单的setonclickListener,它将

工作正常,这是非常简单的方法,谢谢:)

+26

当用户滑动交换机时,不会调用onClick()。 – James 2014-07-10 14:47:50

+1

事实上,这样当用户拖动切换让你没有处理程序。 – 2014-07-11 13:25:08

+0

那么你将如何得到isChecked值,即真或假? – Abhi 2016-08-03 11:15:50

10

另一种可能的方式实现这一目标是通过使用自定义复选框:

public class CheckBox extends AppCompatCheckBox { 
    private OnCheckedChangeListener mListener; 

    public CheckBox(final Context context) { 
     super(context); 
    } 

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

    public CheckBox(final Context context, final AttributeSet attrs, final int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

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

    public void setChecked(final boolean checked, final boolean alsoNotify) { 
     if (!alsoNotify) { 
      super.setOnCheckedChangeListener(null); 
      super.setChecked(checked); 
      super.setOnCheckedChangeListener(mListener); 
      return; 
     } 
     super.setChecked(checked); 
    } 

    public void toggle(boolean alsoNotify) { 
     if (!alsoNotify) { 
      super.setOnCheckedChangeListener(null); 
      super.toggle(); 
      super.setOnCheckedChangeListener(mListener); 
     } 
     super.toggle(); 
    } 
} 

示例用法:

checkBox.setChecked(true,false); 
3

您可以使用此SafeCheckBox类为您的复选框:

public class SafeCheckBox extends AppCompatCheckBox implements CompoundButton.OnCheckedChangeListener { 

    private OnSafeCheckedListener onSafeCheckedListener; 

    private int mIgnoreListener = CALL_LISTENER; 

    public static final int IGNORE = 0; 
    public static final int CALL_LISTENER = 1; 

    @Retention(RetentionPolicy.SOURCE) 
    @IntDef({IGNORE, CALL_LISTENER}) 
    public @interface ListenerMode { 
    } 

    public SafeCheckBox(Context context) { 
     super(context); 
     init(context); 
    } 

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

    public SafeCheckBox(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     init(context); 
    } 

    /** 
    * @param checkState  change state of the checkbox to 
    * @param mIgnoreListener true to ignore the listener else listener will be notified 
    */ 
    public void setSafeCheck(boolean checkState, @ListenerMode int mIgnoreListener) { 
     if (isChecked() == checkState) return; //already in the same state no need to fire listener. 

     if (onSafeCheckedListener != null) { // this to avoid a bug if the user listens for the event after using this method and in that case he will miss first check 
      this.mIgnoreListener = mIgnoreListener; 
     } else { 
      this.mIgnoreListener = CALL_LISTENER; 
     } 
     setChecked(checkState); 
    } 

    private void init(Context context) { 
     setOnCheckedChangeListener(this); 
    } 


    public OnSafeCheckedListener getOnSafeCheckedListener() { 
     return onSafeCheckedListener; 
    } 

    public void setOnSafeCheckedListener(OnSafeCheckedListener onSafeCheckedListener) { 
     this.onSafeCheckedListener = onSafeCheckedListener; 
    } 

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

     if (onSafeCheckedListener != null) 
      onSafeCheckedListener.onAlwaysCalledListener(buttonView, isChecked);// this has to be called before onCheckedChange 
     if (onSafeCheckedListener != null && (mIgnoreListener == CALL_LISTENER)) { 
      onSafeCheckedListener.onCheckedChanged(buttonView, isChecked); 
     } 
     mIgnoreListener = CALL_LISTENER; 
    } 

    /** 
    * Listener that will be called when you want it to be called. 
    * On checked change listeners are called even when the setElementChecked is called from code. :(
    */ 
    public interface OnSafeCheckedListener extends OnCheckedChangeListener { 
     void onAlwaysCalledListener(CompoundButton buttonView, boolean isChecked); 
    } 
} 
  • 然后,你可以拨打电话: -

    setSafeCheck(true,ListenerMode.IGNORE);// OnCheckedChange listener will not be notified

2

使用科特林的扩展与@Shade答案:

1

对于任何人,在这个过程中发现,一个简单的方法做,这是只使用上的复选框标签,然后检查其监听器标签(代码是在科特林):

checkBox.tag = false 
checkBox.setOnCheckedChangeListener{ buttonView, isChecked -> 
    if(checkBox.tag != true) { 
     //Do some stuff 
    } else { 
     checkBox.tag = false 
    } 

然后在访问刚刚设置的标签为true您设置的前

checkBox.tag = true 
checkBox.isChecked = true 

您还可以通过使用需要的一个关键,如果你担心可理解替代setTag方法映射标签的关键:当你想忽略值的变化来器isChecked真实。但是如果它的所有内容都包含在一个类中,那么一些注释字符串将足以解释发生了什么。

0

在检查单选按钮之前将null设置为changeListener。您可以在检查单选按钮后再次设置监听器。

radioGroup.setOnCheckedChangeListener(null); 
radioGroup.check(R.id.radioButton); 
radioGroup.setOnCheckedChangeListener(new 

RadioGroup.OnCheckedChangeListener() { 
    @Override 
    public void onCheckedChanged(RadioGroup radioGroup, @IdRes int i) { 

    } 
}); 
0

我的解决方案用Java编写的基于@克里斯回答:

chkParent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
      @Override 
      public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
       if(buttonView.getTag() != null){ 
        buttonView.setTag(null); 
        return; 
       } 
       if(isChecked){ 
        chkChild.setTag(true); 
        chkChild.setChecked(false); 
       } 
       else{ 
        chkParent.setChecked(true); 
       } 
      } 
}); 

chkChild.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
      @Override 
      public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
       if(buttonView.getTag() != null){ 
        buttonView.setTag(null); 
        return; 
       } 
       if(isChecked){ 
        chkParent.setTag(true); 
        chkParent.setChecked(false); 
       } 
       else{ 
        chkChild.setChecked(true); 
       } 
      } 
}); 

2复选框,并总是一个将被检查(之一必须首先检查虽然)。将标记设置为true可阻止onCheckedChanged侦听器。

0

我的理解,我认为这是最简单的
可能会有所帮助)

public class ProgrammableSwitchCompat extends SwitchCompat { 

    public boolean isCheckedProgrammatically = false; 

    public ProgrammableSwitchCompat(final Context context) { 
     super(context); 
    } 

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

    public ProgrammableSwitchCompat(final Context context, final AttributeSet attrs, final int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    @Override 
    public void setChecked(boolean checked) { 
     isCheckedProgrammatically = false; 
     super.setChecked(checked); 
    } 

    public void setCheckedProgrammatically(boolean checked) { 
     isCheckedProgrammatically = true; 
     super.setChecked(checked); 
    } 
} 

使用它

@Override 
public void onCheckedChanged(CompoundButton compoundButton, boolean on) { 
    if (((ProgrammableSwitchCompat) compoundButton).isCheckedProgrammatically) { 
     return; 
    } 
    //... 
    ((ProgrammableSwitchCompat) compoundButton).setCheckedProgrammatically(true); 
    //... 
    ((ProgrammableSwitchCompat) compoundButton).setCheckedProgrammatically(false); 
    //... 
} 

使用会引发setChecked(boolean)功能
这是所有

0

这是我使用的简单解决方案:
定义自定义监听器:

class CompoundButtonListener implements CompoundButton.OnCheckedChangeListener { 

    boolean enabled = false; 

    @Override 
    public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { 

    } 

    void enable() { 
     enabled = true; 
    } 

    void disable() { 
     enabled = false; 
    } 

    boolean isEnabled() { 
     return enabled; 
    } 
} 

初始化:

CompoundButtonListener checkBoxListener = new CompoundButtonListener() { 
    @Override 
    public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { 
     if (isEnabled()) { 
      // Your code goes here 
     } 
    } 
}; 
myCheckBox.setOnCheckedChangeListener(checkBoxListener); 

用法:

checkBoxListener.disable(); 

// Some logic based on which you will modify CheckBox state 
// Example: myCheckBox.setChecked(true) 

checkBoxListener.enable();