189 votes

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 pour que je puisse appeler

checkbox.setChecked(false);

sans déclencher la onCheckedChanged

317voto

Shade Points 3590

Non, tu ne peux pas le faire. Le site onCheckedChanged est appelée directement à partir de setChecked . Ce que vous pouvez faire est le suivant :

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

Voir le source de CheckBox 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;            
    }
}

121voto

krisDrOid Points 1037

Ajoutez ce code à l'intérieur du OnCheckedChangeListener :

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

Cela nous aidera à déterminer si l'état de la case à cocher a été modifié par un programme ou par une action de l'utilisateur.

31voto

android developer Points 20939

Une autre façon d'y parvenir est d'utiliser une case à cocher personnalisée, qui vous permettra de choisir si vous voulez que l'écouteur soit appelé ou non :

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);
            return;
        }
        super.toggle();
    }
}

Version Kotlin, si vous préférez :

class CheckBox @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : AppCompatCheckBox(context, attrs, defStyleAttr) {
    private var listener: CompoundButton.OnCheckedChangeListener? = null

    override fun setOnCheckedChangeListener(listener: CompoundButton.OnCheckedChangeListener?) {
        this.listener = listener
        super.setOnCheckedChangeListener(listener)
    }

    fun setChecked(checked: Boolean, alsoNotify: Boolean) {
        if (!alsoNotify) {
            super.setOnCheckedChangeListener(null)
            super.setChecked(checked)
            super.setOnCheckedChangeListener(listener)
            return
        }
        super.setChecked(checked)
    }

    fun toggle(alsoNotify: Boolean) {
        if (!alsoNotify) {
            super.setOnCheckedChangeListener(null)
            super.toggle()
            super.setOnCheckedChangeListener(listener)
            return
        }
        super.toggle()
    }
}

utilisation de l'échantillon :

checkBox.setChecked(true,false);

14voto

Chris Points 4076

Si quelqu'un tombe sur ce problème, une façon plus simple de procéder est d'utiliser une balise sur la case à cocher, puis de vérifier cette balise sur son écouteur (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 mettre la balise à true avant de mettre le isChecked à true lorsque vous voulez ignorer le changement de valeur :

checkBox.tag = true
checkBox.isChecked = true

Vous pourriez également faire correspondre la balise à une clé en utilisant la méthode alternative setTag qui requiert une clé si vous vous souciez de la compréhensibilité. Mais si tout est contenu dans une seule classe, quelques chaînes de commentaires seront plus que suffisantes pour expliquer ce qui se passe.

11voto

Joris Points 347

C'est très simple, il suffit de vérifier isPressed à l'intérieur de setOnCheckedChangeListener

Kotlin

switch.setOnCheckedChangeListener { buttonView, isChecked ->
    when {        
        buttonView.isPressed -> {
            foo(isChecked)
        }
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X