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();
}
});
Jak wdrożyć metodę isNotSetByUser()
?
Odpowiedzi:
Odpowiedź 2:
Bardzo prosta odpowiedź:
Użyj na OnClickListener zamiast OnCheckedChangeListener
Teraz odbierasz tylko zdarzenia związane z kliknięciami i nie musisz się martwić o zmiany w programie.
Odpowiedź 1:
Utworzyłem klasę opakowującą (patrz Wzorzec dekoratora), która rozwiązuje ten problem w sposób hermetyzowany:
CheckBox można nadal zadeklarować tak samo w XML, ale użyj tego podczas inicjowania GUI w kodzie:
Jeśli chcesz ustawić sprawdzony z kodu bez wyzwalania nasłuchiwania, wywołaj
myCheckBox.silentlySetChecked(someBoolean)
zamiastsetChecked
.źródło
Switch
odpowiedź 1 działa zarówno w przypadku dotknięcia, jak i przesuwania, podczas gdy odpowiedź 2 działa tylko w przypadku dotknięcia. Zgodnie z osobistą preferencją, rozszerzyłem moją klasęCheckBox
/Switch
zamiast utrzymywać odniesienie do jednej. Dzięki temu wydaje się czystszy (pamiętaj, że musisz podać pełną nazwę pakietu w kodzie XML, jeśli to zrobisz).listener
domyListener
when ilistener
nie jest null. W prawie wszystkich przypadkach to nic nie daje, ale jeśli z jakiegoś powodu stworzymy nowego słuchacza, to nie jest zepsute.Może możesz sprawdzić isShown ()? Jeśli PRAWDA - niż jest to użytkownik. Pracuje dla mnie.
źródło
Wewnątrz po
onCheckedChanged()
prostu sprawdź, czy użytkownik faktycznie machecked/unchecked
przycisk opcji, a następnie wykonaj czynności w następujący sposób:źródło
isPressed
zwraca fałsz, urządzenie Nokia z włączoną funkcją TalkBack.Możesz usunąć odbiornik przed zmianą programistyczną i dodać go ponownie, zgodnie z odpowiedzią w następującym poście SO:
https://stackoverflow.com/a/14147300/1666070
źródło
Spróbuj rozszerzyć CheckBox. Coś takiego (niepełny przykład):
źródło
Jest jeszcze jedno proste rozwiązanie, które działa całkiem nieźle. Przykład dotyczy Switcha.
źródło
Interesujące pytanie. O ile mi wiadomo, kiedy już jesteś w słuchaczu, nie możesz wykryć, jaka akcja wywołała słuchacza, kontekst nie wystarczy. Chyba że używasz zewnętrznej wartości logicznej jako wskaźnika.
Gdy zaznaczysz pole „programowo”, ustaw wcześniej wartość logiczną, aby wskazać, że zostało to zrobione programowo. Coś jak:
Nie zapomnij zresetować stanu pola wyboru w swoim odbiorniku:
źródło
Spróbuj
NinjaSwitch
:Wystarczy zadzwonić,
setChecked(boolean, true)
aby zmienić stan zaznaczenia przełącznika bez wykrycia!źródło
Jeśli
OnClickListener
jest już ustawiona i nie należy jej nadpisywać, użyj!buttonView.isPressed()
jakoisNotSetByUser()
.W przeciwnym razie najlepszym wariantem jest użycie
OnClickListener
zamiastOnCheckedChangeListener
.źródło
Zaakceptowaną odpowiedź można nieco uprościć, aby nie zachowywać odniesienia do oryginalnego pola wyboru. To sprawia, że możemy używać
SilentSwitchCompat
(lubSilentCheckboxCompat
jeśli wolisz) bezpośrednio w XML. Ja również go, dzięki czemu można ustawićOnCheckedChangeListener
, abynull
jeśli chcecie, aby to zrobić.Możesz następnie użyć tego bezpośrednio w swoim XML, w ten sposób (Uwaga: będziesz potrzebować całej nazwy pakietu):
Następnie możesz po cichu zaznaczyć to pole, dzwoniąc pod numer:
źródło
Oto moja realizacja
Kod Java dla przełącznika niestandardowego:
Równoważny kod Kotlin:
Aby zmienić stan przełącznika bez wyzwalania nasłuchiwania, użyj:
Możesz normalnie monitorować zmianę stanu poprzez:
W Kotlinie:
źródło
Mój wariant z funkcjami rozszerzającymi Kotlin:
... niestety za każdym razem musimy przekazywać onCheckedChangeListener, ponieważ klasa CheckBox nie ma funkcji pobierającej dla pola mOnCheckedChangeListener ((
Stosowanie:
źródło
Utwórz zmienną
W aplikacji, gdy zmienisz to zamiast użytkownika, call,
notSetByUser(true)
aby nie było ustawione przez użytkownika, w przeciwnym razie callnotSetByUser(false)
tj. Jest ustawiony przez program.Na koniec, po wywołaniu metody isNotSetByUser () w detektorze zdarzeń upewnij się, że ponownie zmienisz ją z powrotem na normalną.
Wywołaj tę metodę za każdym razem, gdy wykonujesz tę akcję przez użytkownika lub programowo. Wywołaj notSetByUser () z odpowiednią wartością.
źródło
Jeśli tag widoku nie jest używany, możesz go użyć zamiast rozszerzać pole wyboru:
za każdym razem, gdy wywołujesz coś, co zaznacza / odznacza pole wyboru, wywołaj to również przed zaznaczeniem / odznaczeniem:
źródło
Stworzyłem rozszerzenie z prostym RxJava
PublishSubject
. Reaguje tylko na zdarzenia „OnClick”.źródło