Z tego, co przeczytałem, możesz przypisać onClick
programator do przycisku na dwa sposoby.
Za pomocą android:onClick
atrybutu XML, w którym po prostu używasz nazwy metody publicznej z podpisem void name(View v)
lub za pomocą setOnClickListener
metody, w której przekazujesz obiekt implementujący OnClickListener
interfejs. Ta ostatnia często wymaga anonimowej klasy, której osobiście nie lubię (osobisty gust) lub definiowania wewnętrznej klasy, która implementuje OnClickListener
.
Używając atrybutu XML, wystarczy zdefiniować metodę zamiast klasy, więc zastanawiałem się, czy to samo można zrobić za pomocą kodu, a nie w układzie XML.
onClick
atrybutu w pliku układu. Odbywa się to dzięki parametrowiView v
. Po prostu sprawdźif (v == findViewById(R.id.button1
)) itp.v.getId() == R.id.button1
, ponieważ nie musisz znaleźć faktycznej kontroli i dokonać porównania. I możesz użyćswitch
zamiast wielu ifs.Odpowiedzi:
Nie, nie jest to możliwe za pomocą kodu. Android po prostu implementuje
OnClickListener
dla ciebie, gdy definiujeszandroid:onClick="someMethod"
atrybut.Te dwa fragmenty kodu są równe, tylko zaimplementowane na dwa różne sposoby.
Implementacja kodu
Powyżej znajduje się implementacja kodu
OnClickListener
. I to jest implementacja XML.Implementacja XML
W tle Android nie robi nic poza kodem Java, wywołując metodę zdarzenia zdarzenia kliknięcia.
Pamiętaj, że w powyższym pliku XML system Android będzie szukał
onClick
metodymyFancyMethod()
tylko w bieżącym działaniu. Ważne jest, aby pamiętać, jeśli używasz fragmentów, ponieważ nawet jeśli dodasz XML powyżej za pomocą fragmentu, Android nie będzie szukałonClick
metody w.java
pliku fragmentu użytego do dodania XML.Kolejną ważną rzeczą, którą zauważyłem. Wspomniałeś, że nie preferujesz anonimowych metod . Chciałeś powiedzieć, że nie lubisz anonimowych zajęć .
źródło
myFancyMethod()
) w bieżącym działaniu. Jest to ważne, jeśli używasz fragmentów, ponieważ programowy sposób ustawiania detektorów onclick prawdopodobnie będzie miał metodę obsługującą kliknięcia w elemencie onCreateView () fragmentu, w którym nie można go znaleźć, jeśli odwołuje się do niego z XML.Kiedy zobaczyłem najwyższą odpowiedź, uświadomiłem sobie, że moim problemem nie było umieszczenie parametru (View v) w fantazyjnej metodzie:
Próbując uzyskać do niego dostęp z xml, należy użyć
Mam nadzieję, że komuś pomoże.
źródło
android:onClick
dotyczy interfejsu API od poziomu 4, więc jeśli celujesz na <1,6, nie możesz go użyć.źródło
Sprawdź, czy zapomniałeś podać metodę do publicznej wiadomości!
źródło
Podanie
android:onClick
atrybutu powoduje wewnętrzneButton
wywołanie instancjisetOnClickListener
. Dlatego nie ma absolutnie żadnej różnicy.Aby mieć wyraźne zrozumienie, zobaczmy, jak środowisko XML
onClick
obsługuje atrybut.Podczas nadmuchiwania pliku układu tworzone są wszystkie określone w nim widoki. W tym konkretnym przypadku
Button
instancja jest tworzona za pomocąpublic Button (Context context, AttributeSet attrs, int defStyle)
konstruktora. Wszystkie atrybuty w znaczniku XML są odczytywane z pakietu zasobów i przekazywaneAttributeSet
do konstruktora.Button
klasa jest dziedziczona zView
klasy, co powodujeView
wywołanie konstruktora, który dba o ustawienie funkcji obsługi wywołania zwrotnego za pośrednictwemsetOnClickListener
.Atrybut onClick zdefiniowany w pliku attrs.xml jest nazywany w View.java jako
R.styleable.View_onClick
.Oto kod,
View.java
który wykonuje większość pracy dla Ciebie, dzwoniącsetOnClickListener
sam.Jak widać,
setOnClickListener
jest wywoływany w celu zarejestrowania oddzwaniania, tak jak robimy to w naszym kodzie. Jedyną różnicą jest to, że używaJava Reflection
metody wywołania zwrotnego zdefiniowanej w naszym działaniu.Oto powód problemów wymienionych w innych odpowiedziach:
Java Class getMethod
jest używana, wyszukiwane są tylko funkcje ze specyfikatorem publicznego dostępu. W przeciwnym razie przygotuj się naIllegalAccessException
wyjątek.getContext().getClass().getMethod()
call ogranicza wyszukiwanie metod do bieżącego kontekstu, którym jest Activity w przypadku Fragmentu. Dlatego metoda jest przeszukiwana w obrębie klasy Activity, a nie klasy Fragment.Java Class getMethod
wyszukuje metodę, która przyjmujeView.class
jako parametr.źródło
Tutaj są bardzo dobre odpowiedzi, ale chcę dodać jedną linię:
W
android:onclick
XML, Android używa java refleksji za sceną do obsługi tego.I jak wyjaśniono tutaj, odbicie zawsze spowalnia działanie. (szczególnie w Dalvik VM). Rejestracja
onClickListener
jest lepszym sposobem.źródło
Pamiętaj, że jeśli chcesz użyć funkcji XML onClick, odpowiednia metoda powinna mieć jeden parametr, którego typ powinien być zgodny z obiektem XML.
Na przykład przycisk zostanie połączony z twoją metodą poprzez ciąg nazwy:
android:onClick="MyFancyMethod"
ale deklaracja metody powinna pokazywać:...MyFancyMethod(View v) {...
Jeśli próbujesz dodać tę funkcję do elementu menu , będzie ona miała dokładnie taką samą składnię w pliku XML, ale twoja metoda zostanie zadeklarowana jako:
...MyFancyMethod(MenuItem mi) {...
źródło
Innym sposobem ustawienia nasłuchiwaczy kliknięć byłoby użycie XML. Wystarczy dodać atrybut android: onClick do tagu.
Dobrą praktyką jest używanie atrybutu xml „onClick” nad anonimową klasą Java, gdy tylko jest to możliwe.
Przede wszystkim spójrzmy na różnicę w kodzie:
Atrybut XML / atrybut onClick
Część XML
Część Java
Anonimowa klasa Java / setOnClickListener
Część XML
Część Java
Oto zalety korzystania z atrybutu XML nad anonimową klasą Java:
Oczywiście nie zawsze można użyć atrybutu Xml, oto powody, dla których nie wybraliśmy go:
źródło
W Javie 8 prawdopodobnie możesz użyć Method Reference, aby osiągnąć to, czego chcesz.
Załóżmy, że jest to moduł
onClick
obsługi zdarzenia dla przycisku.Następnie przekazujesz
onMyButtonClicked
odwołanie do metody instancji w takimsetOnClickListener()
wywołaniu.Pozwoli ci to uniknąć bezpośredniego definiowania anonimowej klasy. Muszę jednak podkreślić, że metoda Reference w Javie 8 to tak naprawdę tylko cukier składniowy. W rzeczywistości tworzy on dla ciebie instancję anonimowej klasy (tak jak miało to miejsce w wyrażeniu lambda), stąd podobna ostrożność, jak w przypadku wyrejestrowywania programu obsługi zdarzeń zastosowano procedurę obsługi zdarzeń w stylu wyrażenia lambda. Ten artykuł wyjaśnia, że to naprawdę miłe.
PS. Dla tych, którzy ciekawi, jak naprawdę mogę korzystać z funkcji języka Java 8 w Androidzie, jest to dzięki uprzejmości biblioteki retrolambda .
źródło
Tak, możesz zrobić swoje
fragment
lubactivity
wdrożyćView.OnClickListener
a kiedy inicjujesz swoje nowe obiekty widoku w kodzie, możesz to po prostu zrobić
mView.setOnClickListener(this);
i to automatycznie ustawia wszystkie obiekty widoku w kodzie, aby używały
onClick(View v)
metody, którą posiada twójfragment
lubactivity
etc.aby odróżnić widok, który wywołał
onClick
metodę, można użyć instrukcji switch wv.getId()
metodzie.Ta odpowiedź różni się od tej, która mówi „Nie, to niemożliwe za pomocą kodu”
źródło
źródło
Wspierając odpowiedź Ruivo, tak, musisz zadeklarować metodę jako „publiczną”, aby móc korzystać z kliknięcia XML w Androidzie - Rozwijam aplikację kierującą z poziomu API od 8 (minSdk ...) do 16 (targetSdk ...).
Oświadczyłem, że moja metoda jest prywatna i spowodowała błąd, po prostu ogłaszając, że jest świetna.
źródło
Uważaj, chociaż
android:onClick
XML wydaje się być wygodnym sposobem obsługi kliknięcia,setOnClickListener
implementacja robi coś więcej niż dodanieonClickListener
. Rzeczywiście, ustawiła właściwość viewclickable
na true.Chociaż nie jest to problemem w większości implementacji Androida, zgodnie z konstruktorem telefonu, przycisk jest zawsze domyślnie ustawiony na clickable = true, ale inne konstruktory w niektórych modelach telefonów mogą mieć domyślną klikalną = false w widokach innych niż Button.
Więc ustawienie XML nie wystarcza, musisz cały czas zastanawiać się nad dodaniem
android:clickable="true"
przycisku innego niż przycisk, a jeśli masz urządzenie, w którym domyślna jest klikalna = prawda i zapomnisz choć raz umieścić ten atrybut XML, nie zauważysz problem w czasie wykonywania, ale otrzyma informacje zwrotne na rynku, kiedy będą w rękach Twoich klientów!Ponadto nigdy nie możemy być pewni, w jaki sposób proguard zaciemni i zmieni nazwy atrybutów XML i metody klasy, więc nie jest w 100% bezpieczny, że pewnego dnia nigdy nie będą mieli błędu.
Więc jeśli nigdy nie chcesz mieć kłopotów i nigdy o tym nie myśleć, lepiej jest użyć
setOnClickListener
bibliotek takich jak ButterKnife z adnotacjami@OnClick(R.id.button)
źródło
onClick
Atrybut XML określa równieżclickable = true
dlatego, że zwracasetOnClickListener
naView
wewnętrznieZałóżmy, że chcesz dodać zdarzenie kliknięcia w ten sposób
main.xml
W pliku Java musisz napisać metodę taką jak ta.
źródło
Jestem Napisz ten kod w pliku xml ...
I napisz ten kod we fragmencie ...
źródło
Najlepszym sposobem na to jest następujący kod:
źródło
Aby ułatwić Ci życie i uniknąć Anonimowej klasy w setOnClicklistener (), zaimplementuj interfejs View.OnClicklistener w następujący sposób:
klasa publiczna YourClass rozszerza CommonActivity implementuje View.OnClickListener, ...
pozwala to uniknąć:
i idzie bezpośrednio do:
źródło