setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// How to check whether the checkbox/switch has been checked
// by user or it has been checked programatically ?
if (isNotSetByUser())
return;
handleSetbyUser();
}
});
Como implementar o método isNotSetByUser()
?
Respostas:
Resposta 2:
Uma resposta muito simples:
Use OnClickListener em vez de OnCheckedChangeListener
Agora você só seleciona eventos de clique e não precisa se preocupar com alterações programáticas.
Resposta 1:
Eu criei uma classe de wrapper (consulte Decorator Pattern) que lida com esse problema de forma encapsulada:
CheckBox ainda pode ser declarado o mesmo em XML, mas use isso ao inicializar sua GUI no código:
Se você deseja definir verificado a partir do código sem acionar o ouvinte, chame em
myCheckBox.silentlySetChecked(someBoolean)
vez desetChecked
.fonte
Switch
, a resposta 1 funciona em casos de toque e slide, enquanto a resposta 2 só funcionará no caso de toque. Como preferência pessoal, fiz minha classe estenderCheckBox
/Switch
ao invés de manter uma referência a um. Parece mais limpo dessa forma (observe que você deve especificar o nome completo do pacote no XML se fizer isso).listener
amyListener
quandolistener
não for nulo. Em quase todos os casos, isso não faz nada, mas se criarmos um novo ouvinte por algum motivo, isso não será quebrado.Talvez você possa verificar isShown ()? Se TRUE - do que o usuário. Funciona para mim.
fonte
Dentro do,
onCheckedChanged()
basta verificar se o usuário tem realmentechecked/unchecked
o botão de opção e fazer as coisas de acordo da seguinte maneira:fonte
isPressed
retorna falso, dispositivo Nokia com TalkBack ativado.Você pode remover o ouvinte antes de alterá-lo programaticamente e adicioná-lo novamente, conforme respondido na seguinte postagem do SO:
https://stackoverflow.com/a/14147300/1666070
fonte
Tente estender o CheckBox. Algo assim (exemplo não completo):
fonte
Existe outra solução simples que funciona muito bem. O exemplo é para Switch.
fonte
Pergunta interessante. Pelo que sei, uma vez que você está no ouvinte, você não pode detectar qual ação acionou o ouvinte, o contexto não é suficiente. A menos que você use um valor booleano externo como indicador.
Quando você marca a caixa "programaticamente", defina um valor booleano antes para indicar que foi feito programaticamente. Algo como:
E em seu ouvinte, não se esqueça de redefinir o estado da caixa de seleção:
fonte
Experimente
NinjaSwitch
:Basta chamar
setChecked(boolean, true)
para alterar o estado verificado do switch sem ser detectado!fonte
Se
OnClickListener
já estiver definido e não deve ser substituído, use!buttonView.isPressed()
comoisNotSetByUser()
.Caso contrário, a melhor variante é usar em
OnClickListener
vez deOnCheckedChangeListener
.fonte
A resposta aceita pode ser um pouco simplificada para não manter uma referência à caixa de seleção original. Isso permite que possamos usar o
SilentSwitchCompat
(ouSilentCheckboxCompat
se preferir) diretamente no XML. Eu também fiz isso para que você possa definir oOnCheckedChangeListener
comonull
se desejar.Você pode então usar isso diretamente em seu XML da seguinte maneira (Observação: você precisará de todo o nome do pacote):
Em seguida, você pode marcar a caixa silenciosamente chamando:
fonte
Aqui está minha implementação
Código Java para troca personalizada:
Código Kotlin equivalente:
Para alterar o estado do switch sem acionar o ouvinte, use:
Você pode monitorar a mudança de estado normalmente:
Em Kotlin:
fonte
Minha variante com funções de extensão Kotlin:
... infelizmente, precisamos passar onCheckedChangeListener todas as vezes porque a classe CheckBox não tem um getter para o campo mOnCheckedChangeListener ((
Uso:
fonte
Crie uma variável
No aplicativo, quando você alterar em vez do usuário, chame de
notSetByUser(true)
forma que não seja definido pelo usuário, senão chame,notSetByUser(false)
ou seja, ele é definido pelo programa.Por último, em seu ouvinte de evento, depois de chamar isNotSetByUser (), certifique-se de alterá-lo novamente para o normal.
Chame esse método sempre que estiver manipulando essa ação por meio do usuário ou programaticamente. Chame notSetByUser () com o valor apropriado.
fonte
Se a tag da visualização não for usada, você pode usá-la em vez de estender a caixa de seleção:
cada vez que você chamar algo que marque / desmarque a caixa de seleção, chame também antes de marcar / desmarcar:
fonte
Criei uma extensão com RxJava
PublishSubject
, simples. Reage apenas a eventos "OnClick".fonte