poniedziałek, 10 lutego 2014

Obsługa zdarzenia kliknięcia na komponent


Kod źródłowy do tej lekcji znajduje się tutaj. Rozpakuj go i zaimportuj. W katalogu z kodem źródłowym znajdą się podkatalogi oznaczone numerami. Są to po prostu kolejne wersje kodu, tworzonego w ramach przykładów. Możesz analizować kolejne kroki tworzenia aplikacji, lub od razu zabrać się za kod z katalogu o najwyższym numerku.

Obsługiwać zdarzenie kliknięcia komponentu można na kilka sposobów. Przedstawię trzy najpopularniejsze. Do wszystkich trzech sposobów będzie nam potrzebny jakiś komponent na którego kliknięcie będziemy reagować. Z tego powodu przyklejam na ekranie jeden przycisk.



Pierwszy najprostszy w przygotowaniu i chyba najbardziej przejrzysty, ale też najmniej czytelny i wymagający dużo kodu. Tworzymy osobno listener kliknięcia (czyli słuchacza zdarzenia kliknięcia – czeka aż klikniesz i reaguje) i podpinamy go do guzika:


 
To co się ma wydarzyć w wyniku kliknięcia jest opisane w metodzie onClickk listenera. W tym przypadku jest to wyświetlenie komunikatu Toast z tekstem „om nom nom” (linia 23). Samo podpięcie stworzonego listenera odbywa się w linii 27.




Alternatywnie choć na podobnej zasadzie możemy utworzyć obiekt listenera w momencie jego tworzenia – linia 19. Mniej kodu, ale czytelność na tym traci. Efekt działania identyczny jak poprzednio.



Trzecia alternatywna metoda jest chyba najmniej intuicyjna, ale jak się zrozumie zasadę działania to kod przy większej ilości guzików do obsługi będzie najbardziej przejrzysty i bardzo wygodny w rozwijaniu. Tym razem nie definiuję żadnego listenera! Wszystko co ma się zdarzyć po kliknięciu przycisku jest opisane w metodzie obslugaKlikniecia. Wazne by metoda ta przyjmowala jako parametr obiekt klasy View (po tej klasie dziedziczą wszystkie komponenty takie jak guzik i to właśnie pod postacią tego parametru jest przekazywany obiekt komponentu do metody) i nic nie zwracała. Pozornie metoda jako taka nie jest w żaden sposób związana z obsługą kliknięcia na przycisk:



Magia zaczyna dziać się dopiero w pliku layoutu związanym z tą aktywnością:


Pojawił nam się tutaj (linia 19) nowy element: android:onClick. Zamiast związywać na poziomie kodu javowego metodę obslugaKlikniecia z specjalnie do tego tworzonym listenerem, wskazujemy nazwę metody przy użyciu parametru przycisku w pliku layoutu. Takie rozwiązanie ma ten plus, że pisze się znacznie mniej kodu, a sam kod przy większej liczbie obsługiwanych przycisków jest czytelniejszy. Z drugiej strony, jeśli nie będziemy pamiętać o takim rozwiązaniu, możemy za jakiś czas zachodzić w głowę jak to zostało zrobione :)
Pamiętajmy że obsługa kliknięcia nie dotyczy tylko przycisków, ale każdego komponentu dziedziczącego po View – w tym napisy i pola edycyjne.




23 komentarze:

  1. Hej, super tutorial, ale pojawiły mi się błędy:

    The method onClick(View) of type new DialogInterface.OnClickListener(){} must override or implement a supertype method
    The method setOnClickListener(View.OnClickListener) in the type View is not applicable for the arguments (new DialogInterface.OnClickListener(){})

    OdpowiedzUsuń
    Odpowiedzi
    1. http://stackoverflow.com/questions/6071799/setonclicklistenerview-onclicklistener-in-the-type-view-is-not-applicable-for

      Ok poszło, te importy..pain in the ass

      Usuń
    2. Importujesz nie tą klasę :)

      Usuń
  2. Witam

    Mogę zapytać co oznacza "@Override"?

    OdpowiedzUsuń
  3. To oznacza, że metoda ta nadpisuje inną metodę (o tej samej nazwie i parametrach), którą odziedziczyła z klasy nadrzędnej. To tylko element informacyjny, nie wpływa w żadnym wypadku na działanie programu ;)

    OdpowiedzUsuń
  4. Czy dodanie image button wygląda tak samo?

    OdpowiedzUsuń
  5. Zrobilem trzecia metode i uruchamia mi sie aplikacja na tel ale gdy klikne na button to sie wylacza, dlaczego?

    OdpowiedzUsuń
    Odpowiedzi
    1. mi wywalało aplikacje na telefonie przy wybraniu 1 i 2 metody obslugi klikniecia. Przy 3 metodzie wszystko jest ok, nie wiem od czego to zalezy

      Usuń
  6. Genialny kurs!
    W porównaniu z innymi dostępnymi za darmo po polsku w internecie ten jest naprawdę godny uwagi.

    Dziękuję

    OdpowiedzUsuń
  7. Dzień dobry, mam problem z wykonaniem większości przykładów z kursu. U mnie wygenerowany przez kreator kod źródłowy wygląda trochę inaczej. Activity jest rozdzielone na 2 części - 1 puste i to w którym domyślnie dodawany jest tekst Hello world! jako drugie o nazwie fragment_main.xml. Jeśli tam dodaję komponenty i następnie odwołuję się do nich w funkcji onCreate to nie mogę nic zmieniać - znalezienie elementu i przypisanie go do zmiennej jest możliwe, jednak próba zapisania innego napisu kończy się błędem podobnym do niebezpiecznego dostępu do zmiennej innego wątku w .net. Gdzie powinienem umieszczać swój kod? Próbowałem w onCreateView, ale tutaj nie mogę znaleźć komponentów. Domyślny kod wygląda tak: https://gist.github.com/anonymous/5ac6be099ca7411d72ad

    OdpowiedzUsuń
    Odpowiedzi
    1. Cześć wszystkim. Też chętnie bym się dowiedział jak wygląda obsługa domyślnego fragment_main, który pojawił się w Eclipse nie dawno po którejś aktualizacji. Póki co po prostu go wywalam i robię wszystko w activity_main, jednak wiem że nie jest to do końca poprawne.. Pozdrawiam.

      Usuń
    2. podbijam ... mam identyczny problem, na poczatku mialem problem z przypisaniem przycisku bo findViewByID zwracal NULL , z tym sobie juz poradzilem jednak setText nie zmienia wartosci pola tekstowego i nie wiem co jest nie tak..

      Usuń
  8. Mam identyczny kod jak w pierwszym przykładzie i mam import android.view.View.OnClickListener. Niestety wywala mi dużo błędów o co z tym chodzi

    OdpowiedzUsuń
  9. dlaczego nie mam tych numerków przy kodzie źródłowym ?

    OdpowiedzUsuń
  10. Czemu przy wykorzytaniu 1 sposobu aplikacja od razu wywala do pulpitu?

    OdpowiedzUsuń
  11. Powiem tak - poradnik idzie w dobrym kierunku, aczkolwiek póki co jest ... Kiepski. Po prostu kiepski.
    Ogarniam podstawy programowania kilku języków, nie ogarniam javy. Teoretycznie to powinno wystarczyć, by przejść ten tutorial, nie? A jednak nie... Import odpowiedniej klasy to już jest jakiś... Mogłeś się bardziej postarać :)

    OdpowiedzUsuń
  12. Jezu Panowie programuję w różnych językach -ale takiego sajgonu jak w "java" nie widziałem żeby obsłużyć przycisk np: onClick w innych programach do programowania wystarczy kliknąć na przycisk "button" generuje się sama procedura, tutaj trzeba się napisać żeby wyświetlić tekst np "OOO d PA". Programowanie w java porażka. Czy trzeba wracać do pisania w notatniku jak za dawnych lat (makabra - jeszcze importowanie), Życzę powodzenia.

    OdpowiedzUsuń
    Odpowiedzi
    1. Panie Anonimowy, jak pan powinien wiedzieć Java jest bardzo dziurawa i podatna na ataki wirusów. A że jeszcze się rozwija to ja się nie dziwię że tu jest ttak nawalone bez sensu.

      Usuń
  13. Mam problem z metodą onClick. Jak definiuje obsługę kliknięcia wywala mi taki o to błąd:
    -compile:
    [javac] Compiling 3 source files to /home/nikodem/Pulpit/NT3/PlanLekcji/bin/classes
    [javac] /home/nikodem/Pulpit/NT3/PlanLekcji/src/org/narzew/timetable2/Dzwonki.java:9: error: cannot find symbol
    [javac] public void return_clicked(View v){
    [javac] ^
    [javac] symbol: class View
    [javac] location: class Dzwonki
    [javac] /home/nikodem/Pulpit/NT3/PlanLekcji/src/org/narzew/timetable2/PlanLekcji.java:8: error: cannot find symbol
    [javac] public void dzwonki_clicked(View v){
    [javac] ^
    [javac] symbol: class View
    [javac] location: class PlanLekcji
    [javac] 2 errors

    Fragment kodu:
    public void dzwonki_clicked(View v){
    setContentView(R.layout.dzwonki);
    }

    public void return_clicked(View v){
    setContentView(R.layout.main);
    }

    Może mi ktoś powiedzieć co robię źle ?

    OdpowiedzUsuń
  14. witam,
    a co dopisać, aby po kliknięciu na button wysłało przez BT jakąś cyfrę liczbę, czy nawet znak...
    zakładam, zę obsługę BT juz mam zaimplementowaną :)

    OdpowiedzUsuń
  15. Można wszystko skrócić do np:


    public void Tekst(View view) {

    Toast.makeText(getApplicationContext(), "Elo śmieciu hehe", Toast.LENGTH_SHORT ).show();




    }

    pozdrawiam

    OdpowiedzUsuń