我setOnCheckedChangeListener
實現我checkbox
,而不會觸發onCheckChanged
變化選擇框的值是否有一種方法,我可以叫
checkbox.setChecked(false);
而不觸發onCheckedChanged
我setOnCheckedChangeListener
實現我checkbox
,而不會觸發onCheckChanged
變化選擇框的值是否有一種方法,我可以叫
checkbox.setChecked(false);
而不觸發onCheckedChanged
不,你不能這樣做。 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;
}
}
我猜使用反射是唯一的出路。事情是這樣的:
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();
}
另一種可能的方式實現這一目標是通過使用自定義複選框:
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);
您可以使用此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
使用科特林的擴展與@Shade答案:
對於任何人,在這個過程中發現,一個簡單的方法做,這是隻使用上的複選框標籤,然後檢查其監聽器標籤(代碼是在科特林):
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真實。但是如果它的所有內容都包含在一個類中,那麼一些註釋字符串將足以解釋發生了什麼。
在檢查單選按鈕之前將null設置爲changeListener。您可以在檢查單選按鈕後再次設置監聽器。
radioGroup.setOnCheckedChangeListener(null);
radioGroup.check(R.id.radioButton);
radioGroup.setOnCheckedChangeListener(new
RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, @IdRes int i) {
}
});
我的解決方案用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偵聽器。
我的理解,我認爲這是最簡單的
可能會有所幫助)
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)
功能
這是所有
這是我使用的簡單解決方案:
定義自定義監聽器:
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();
你打算如何讓'mListener'? 'Checkbox'沒有getCheckChangeListener的吸氣劑 – tir38 2014-07-08 19:56:18
好吧,不需要簡單地downvote,因爲你不明白解決方案。 'mListener'是由程序員創建的'OnCheckChangedListener'接口的一個實現。我的答案意味着程序員保留了對**自己的實現** - 'mListener'的引用。 – Shade 2014-07-09 08:20:52
如果您想重複使用setChecked()方法,更改偵聽器會是低效的嗎? – Ren 2016-04-22 22:01:20