2013-03-20 45 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();