Changer la valeur de la case à cocher sans déclencher onCheckChanged

j'ai setOnCheckedChangeListener mis en œuvre pour mon checkbox

y a-t-il un moyen que je puisse appeler

checkbox.setChecked(false);

sans déclencher le onCheckedChanged

99
demandé sur Archie.bpgc 2013-03-20 16:10:54

15 réponses

Non, tu ne peux pas le faire. La méthode onCheckedChanged est appelée directement de setChecked . Ce que vous pouvez faire est le suivant:

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

voir la source de la case à cocher , et la mise en œuvre de 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;            
    }
}
216
répondu Shade 2016-09-23 16:49:11

une autre façon d'y parvenir est d'utiliser une case à cocher personnalisée:

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();
    }
}

exemple d'utilisation:

checkBox.setChecked(true,false);
14
répondu android developer 2017-03-28 08:15:51

vous utilisez simplement setonclickListener , il fonctionnera très bien et c'est méthode très simple, merci:)

9
répondu Rohit 2013-03-20 13:22:28

vous pouvez utiliser cette classe SafeCheckBox comme votre case à cocher :

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);
    }
}
  • alors vous pouvez appeler: -

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

3
répondu krishan 2016-04-07 04:30:06

utilisant les extensions de Kotlin avec la réponse de @Shade:

fun CompoundButton.setCustomChecked(value: Boolean,listener: CompoundButton.OnCheckedChangeListener) {
     setOnCheckedChangeListener(null)
     isChecked = value
     setOnCheckedChangeListener(listener)
}
3
répondu Mickey Mouse 2017-06-30 18:33:33

pour quiconque trébuche à travers ceci, une façon plus simple de le faire est d'utiliser une balise sur la case à cocher et ensuite vérifier cette balise sur son auditeur (le code est en Kotlin):

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

ensuite, lors de l'accès, il suffit de définir la balise à true avant de définir l'isChecked à true lorsque vous voulez ignorer le changement de valeur:

checkBox.tag = true
checkBox.isChecked = true

vous pouvez également mapper la balise à une clé en utilisant la méthode setTag alternative qui nécessite une clé si vous étiez inquiet au sujet de la compréhensibilité. Mais si son tout contenu à une seule classe quelques chaînes de commentaires seront plus que suffisant pour expliquer ce qui se passe.

2
répondu Chris 2017-07-12 20:10:22

régler null à changeListener avant de vérifier le bouton radio. Vous pouvez régler l'écouteur à nouveau après Vérifier le bouton radio.

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

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

   }
});
1
répondu gencaysahinn 2017-07-26 14:01:52

mon interprétation qui je pense est la plus facile

Peut être utile)

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);
    }
}

utiliser

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

l'utilisation déclenchera setChecked(boolean) fonction

c'est tout

1
répondu V. Kalyuzhnyu 2017-08-17 16:12:27

je suppose qu'utiliser la réflexion est le seul moyen. Quelque chose comme ceci:

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
répondu Zielony 2013-03-20 12:26:00

ma solution écrite en java basée sur la réponse de @Chris:

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 cases à cocher et toujours une case à cocher (une case à cocher doit être cochée au départ). Définir la balise aux blocs true sur l'écouteur modifiéchecké.

0
répondu Makalele 2017-08-03 08:02:18

c'est une solution simple que j'ai utilisé:

définir un auditeur personnalisé:

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;
    }
}

initialisation:

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

Utilisation:

checkBoxListener.disable();

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

checkBoxListener.enable();
0
répondu vovahost 2017-08-31 10:41:09
public void setCheckedChangeListenerSwitch() {

    switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean selected) {

            if (selected) {
                // do something
            } else {
                // do something else
            }

        }
    });

}

// Update state & reset listener (so onCheckedNot called)
public void updateSwitchState(boolean state){

    switch.setOnCheckedChangeListener(null);
    switch.setChecked(state);
    setCheckedChangeListenerSwitch();

}
0
répondu codebyjames 2018-03-25 05:11:19

que dis-tu de ça? Essayez d'utiliser la Balise

mCheck.setTag("ignore");
mCheck.setChecked(true);
mCheck.setTag(null);

et

switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton, boolean selected) {

            //If switch has a tag, ignore below
            if(compoundButton.getTag() != null)
                return; 

            if (selected) {
                // do something
            } else {
                // do something else
            }

        }
    });
0
répondu areema 2018-08-14 07:32:36

j'ai trouvé toutes les réponses ci-dessus, trop compliqués. Pourquoi ne pas créer votre propre drapeau avec un simple booléen?

il suffit d'utiliser un système de drapeau simple avec un booléen. Créer boolean noListener . Chaque fois que vous voulez activer/désactiver votre interrupteur sans utiliser de code (dans cet exemple, représenté par runListenerCode() , mettez simplement noListener=true avant d'appeler switch.setChecked(false/true)

switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
           @Override
           public void onCheckedChanged(CompoundButton compoundButton, boolean selected) {
               if (!noListener) { //If we want to run our code like usual
                   runListenerCode();
               } else { //If we simply want the switch to turn off
                   noListener = false;
               }
           });

solution très simple en utilisant simple drapeau. À la fin, nous réglons noListener=false une fois de plus pour que notre code continue de fonctionner. Espérons que cette aide!

0
répondu Ruchir Baronia 2018-08-15 01:33:35

mettez ce chèque à L'intérieur Surcheckedchangelistener: compoundButton.isPressed ()

le code réel devrait être comme ci-dessous:

if (!compoundButton.isPressed()) { retourner; }

indique le statut, que l'interrupteur ait été réglé de façon grammaticale ou par geste de la main.

0
répondu krisDrOid 2018-10-02 10:21:06