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
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
J'ai trouvé toutes les réponses ci-dessus bien trop compliquées. Pourquoi ne pas simplement créer votre propre drapeau avec un simple booléen ?
Il suffit d'utiliser un simple système de drapeau avec un booléen. Créer boolean noListener
. Chaque fois que vous voulez activer/désactiver votre interrupteur sans exécuter de code (dans cet exemple, représenté sous la forme de runListenerCode()
il suffit de mettre 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. A la fin, nous mettons noListener=false
une fois de plus pour que notre code continue à fonctionner. J'espère que cela vous aidera !
J'ai utilisé un ReentrantLock
et le verrouiller quand je suis en train de régler isChecked
:
Kotlin :
// 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();
}
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 l'une d'entre elles sera cochée (l'une d'entre elles doit cependant être cochée au départ). Le fait de mettre le tag à true bloque l'écouteur onCheckedChanged.
Je ne voulais pas vraiment avoir à passer l'écouteur à chaque fois que l'on vérifiait les changements, ni utiliser la fonction enabled
comme moyen de déterminer si nous devons définir la valeur (que se passe-t-il dans le cas où nous avons déjà désactivé l'interrupteur lors de la définition de la valeur ?)
Au lieu de cela, j'utilise des balises avec un identifiant et quelques méthodes d'extension que vous pouvez appeler :
fun CompoundButton.setOnCheckedWithoutCallingChangeListener(
listener: (view: CompoundButton, checked: Boolean) -> Unit
) {
setOnCheckedChangeListener { view, checked ->
if (view.getTag(R.id.compound_button_checked_changed_listener_disabled) != true) {
listener(view, checked)
}
}
this.setTag(R.id.compound_button_enabled_checked_change_supported, true)
}
fun CompoundButton.setCheckedWithoutCallingListener(checked: Boolean) {
check(this.getTag(R.id.compound_button_enabled_checked_change_supported) == true) {
"Must set listener using `setOnCheckedWithoutCallingChangeListener` to call this method"
}
setTag(R.id.compound_button_checked_changed_listener_disabled, true)
isChecked = checked
setTag(R.id.compound_button_checked_changed_listener_disabled, false)
}
Vous pouvez maintenant appeler setCheckedWithoutCallingListener(bool)
et il appliquera l'utilisation correcte de l'écouteur.
Vous pouvez aussi toujours appeler setChecked(bool)
pour renvoyer l'écouteur si vous en avez encore besoin
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.