J'ai setOnCheckedChangeListener
implémenté pour ma checkbox
Puis-je appeler
checkbox.setChecked(false);
sans déclencher la onCheckedChanged
Non, tu ne peux pas le faire. La méthode 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 la source de CheckBox , et l'implémentation 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;
}
}
Un autre moyen possible d'y parvenir consiste à utiliser une CheckBox personnalisée, qui vous permettra de choisir si vous souhaitez appeler l'auditeur 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);
}
super.toggle();
}
}
exemple d'utilisation:
checkBox.setChecked(true,false);
vous utilisez simplement setonclickListener, cela fonctionnera très bien et ceci est une méthode très simple, merci :)
Ajoutez ce code dans OnCheckedChangeListener:
if(!compoundButton.isPressed()) {
return;
}
Cela nous aidera à comprendre que l'état de checkBox météo a été modifié par programme ou par l'action de l'utilisateur.
En utilisant les extensions de Kotlin avec @Shade, vous répondez:
fun CompoundButton.setCustomChecked(value: Boolean,listener: CompoundButton.OnCheckedChangeListener) {
setOnCheckedChangeListener(null)
isChecked = value
setOnCheckedChangeListener(listener)
}
Pour tous ceux qui tombent sur cela, une façon plus simple de le faire est simplement 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, définissez simplement la balise sur true avant de définir isChecked sur true lorsque vous souhaitez ignorer le changement de valeur:
checkBox.tag = true
checkBox.isChecked = true
Vous pouvez également mapper le tag sur une clé en utilisant la méthode alternative setTag qui nécessite une clé si vous êtes inquiet pour 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.
Définissez la valeur null sur changeListener avant de cocher le bouton radio. Vous pouvez réactiver l'auditeur après avoir coché 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) {
}
});
C'est une solution simple que j'ai utilisée:
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();
Mon interprétation que je pense être 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);
}
}
utilise le
@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 la fonction setChecked(boolean)
c'est tout
J'ai trouvé toutes les réponses ci-dessus trop compliquées. Pourquoi ne pas simplement créer votre propre drapeau avec un simple booléen?
Utilisez simplement un système de drapeau simple avec un booléen. Créez boolean noListener
. Chaque fois que vous souhaitez activer/désactiver votre commutateur sans exécuter de code (dans cet exemple, représenté par runListenerCode()
, définissez 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 utilisant des drapeaux simples. À la fin, nous redéfinissons noListener=false
pour que notre code continue à fonctionner. J'espère que cela t'aides!
J'ai utilisé un ReentrantLock
et le verrouille chaque fois que je règle isChecked
:
// lock when isChecked is being set programmatically
val isBeingProgrammaticallySet = ReentrantLock()
// set isChecked programmatically
isBeingProgrammaticallySet.withLock()
{
checkbox.isChecked = true
}
// do something only when preference is modified by user
checkbox.setOnCheckedChangeListener()
{
_,isChecked ->
if (isBeingProgrammaticallySet.isHeldByCurrentThread.not())
{
// do it
}
}
Je suppose que l'utilisation de la réflexion est le seul moyen. Quelque chose comme ça:
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();
}
Que diriez-vous de ceci . Essayez d'utiliser Tag in View
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
}
}
});
Ma solution écrite en Java basée sur la réponse @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 sera cochée (une doit être cochée au départ si). Définition de la balise sur true blocks onCheckedChanged listener.
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();
}