mam setOnCheckedChangeListener
realizowane dla mojego checkbox
Zmień wartość Pole wyboru bez wyzwalania onCheckChanged
Czy istnieje sposób mogę zadzwonić
checkbox.setChecked(false);
bez wyzwalania onCheckedChanged
mam setOnCheckedChangeListener
realizowane dla mojego checkbox
Zmień wartość Pole wyboru bez wyzwalania onCheckChanged
Czy istnieje sposób mogę zadzwonić
checkbox.setChecked(false);
bez wyzwalania onCheckedChanged
Nie, nie mogę tego zrobić . Metoda onCheckedChanged
jest wywoływana bezpośrednio z setChecked
. Co można zrobić, jest następujący:
mCheck.setOnCheckedChangeListener (null);
mCheck.setChecked (false);
mCheck.setOnCheckedChangeListener (mListener);
Zobacz source of CheckBox i realizacja 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;
}
}
Chyba stosując odbicie jest jedynym sposobem. Coś takiego:
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();
}
Może działać, dopóki deweloperzy nie zmienią nazwy pól lub, na przykład, nie podniosą metody "isChecked" w hierarchii ... lub nie dokonają kolejnego refaktoryzacji ... Przynajmniej dodaj coś takiego: 'if (Build.VERSION.SDK_INT <= Build.VERSION_CODES .JELLY_BEAN) {/ * do reflection * /} ' – aeracode
Błędnym pomysłem jest zachęcanie do przełamania API i zagłębienia się w elementy wewnętrzne. Wszelkie zmiany w implementacji spowodują awarię aplikacji. – mspanc
użyć po prostu setonclickListener, że będzie działa dobrze i jest to bardzo prosta metoda, dzięki :)
Innym możliwym sposobem osiągnięcia tego celu jest za pomocą niestandardowego checkbox:
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();
}
}
wykorzystanie próbki:
checkBox.setChecked(true,false);
można użyć tej klasy SafeCheckBox jako wyboru:
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);
}
}
Następnie można nazwać: -
setSafeCheck(true,ListenerMode.IGNORE);// OnCheckedChange listener will not be notified
Używanie rozszerzeń Kotlin jest z @Shade odpowiedź:
Dla każdego, kto potyka się o to, jeden prostszy sposób to zrobić, to po prostu użyć tagu pole wyboru, a następnie sprawdzić, czy znacznik na jego słuchacza (kod znajduje się Kotlin):
checkBox.tag = false
checkBox.setOnCheckedChangeListener{ buttonView, isChecked ->
if(checkBox.tag != true) {
//Do some stuff
} else {
checkBox.tag = false
}
Następnie przy dostępie tylko ustawić znacznik true zanim ustaw IsChecked true, jeśli chcesz, aby zignorować zmiany wartość:
checkBox.tag = true
checkBox.isChecked = true
można również mapować tag do klucza za pomocą alternatywnej metody setTag który wymaga klucza jeśli byli zaniepokojeni zrozumiałość. Ale jeśli wszystko to jest zawarte w jednej klasie, kilka ciągów komentarzy będzie więcej niż wystarczająco, aby wyjaśnić, co się dzieje.
Set null changeListener przed przyciskiem radiowym check. Możesz ustawić detektor ponownie po zaznaczeniu opcji radiowej.
radioGroup.setOnCheckedChangeListener(null);
radioGroup.check(R.id.radioButton);
radioGroup.setOnCheckedChangeListener(new
RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, @IdRes int i) {
}
});
Moje rozwiązanie napisany w języku Java na podstawie @Chris odpowiedź:
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 pól i zawsze jeden będzie sprawdzane (jeden musi być wstępnie sprawdzone chociaż). Ustawienie znacznika na prawdziwe bloki na detektoru listenedCheckedChanged.
Moja interpretacja, która myślę, że to najprostszy
mogą być pomocne)
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);
}
}
używać
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean on) {
if (((ProgrammableSwitchCompat) compoundButton).isCheckedProgrammatically) {
return;
}
//...
((ProgrammableSwitchCompat) compoundButton).setCheckedProgrammatically(true);
//...
((ProgrammableSwitchCompat) compoundButton).setCheckedProgrammatically(false);
//...
}
użycie spowoduje setChecked(boolean)
funkcja
to wszystko
Jest proste rozwiązanie, którego używałem:
Definiowanie niestandardowego słuchacza:
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;
}
}
Inicjalizacja:
CompoundButtonListener checkBoxListener = new CompoundButtonListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
if (isEnabled()) {
// Your code goes here
}
}
};
myCheckBox.setOnCheckedChangeListener(checkBoxListener);
Zastosowanie:
checkBoxListener.disable();
// Some logic based on which you will modify CheckBox state
// Example: myCheckBox.setChecked(true)
checkBoxListener.enable();
Jak można zaproponować, aby 'mListener'? 'Checkbox' nie ma gettera dla jego' OnCheckChangeListener' – tir38
No cóż, nie trzeba się zgodzić tylko dlatego, że nie rozumiesz rozwiązania. 'mListener' jest implementacją interfejsu' OnCheckChangedListener', który został stworzony przez programistę. Moja odpowiedź sugeruje, że programista utrzymywał odniesienie do ** własnej implementacji ** - 'mListener'. – Shade
Czy zmiana słuchacza jest nieefektywna, jeśli chcesz wielokrotnie używać metody setChecked()? – Ren