poniedziałek, 17 lutego 2014

Wywoływanie aktywności (ekranów) , elementy graficzne Button, EditText, TextView - podsumowanie podstaw


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.


-W tej lekcji zajmiemy się wywoływaniem nowych aktywności (czyli przechodzeniem pomiędzy ekranami), a także elementami Button, EditText oraz TextView. Stworzymy przy okazji prosty program do obliczania pól figur geometrycznych.
Zaczynamy od stworzenia projektu. Z menu wybieramy „Android Application Project”:



Dalej nadajemy naszej aplikacji nazwę:


Przy tworzeniu projektu, tworzymy również od razu pierwszą aktywność. Będzie to po prostu pierwszy ekran jaki się pojawi po uruchomieniu aplikacji. Decydujemy o jego pokroju - zostawiamy domyślne „Blank Activity”:


Podajemy nazwę klasy będącej pierwszą aktywnością (ekranem) w polu „Activity Name”. Do naszej klasy będzie też potrzebny plik XML w którym to określimy jak mają być rozmieszczone elementy w danej aktywności (guziki, okienka etc). Nazwę tego pliku określamy w polu „Layout Name”:


Gdy projekt zostanie utworzony, zostanie otwarta klasa głównej aktywności. Będzie zawierać dwie metody. Pierwsza „onCreate” to metoda która jest uruchamiana w momencie startu aktywności. Druga „onCreateOptionsMenu” to metoda uruchamiana kiedy ktoś wybierze przycisk menu. Tę drugą usuwamy, nie jest nam na razie potrzebna.


Nasza klasa powinna wyglądać teraz mniej więcej tak:



Zadbamy teraz o wygląd pierwszego ekranu. Przechodzimy do pliku layoutu. Powinniśmy zobaczyć taki ekran. Po prawej mamy naszą aktywność, po lewej paletę komponentów. Gdyby zamiast aktywności widoczny był kod XML, wybierz z zakładek na dole „Graphical Layout”:



Zawczasu przygotowałem sobie kilka obrazków które będą mi potrzebne w aplikacji (narysowałem w Paincie :p ). Będziemy ich używać w naszej aplikacji. Zrobimy sobie listę figur pojawiającą się na „Dzień dobry” wraz z obrazkami. Po kliknięciu na nazwę figury program przejdzie do formularza służącego obliczaniu pola danej figury.



Muszę je teraz umieścić w projecie. Zaznaczam je w katalogu, robię CTRL+C, w projekcie wchodzę w podkatalog res, następnie drawable-hdpi (lub inny drawable-....) i robię CRTL+V:



Przechodzę teraz do edycji pliku XML określającego layout naszej głównej aktywności. Będziemy edytować ręcznie, więc tym razem nie wybieramy „Graphical Layout” a „activity_main.xml” (lub jak tam nazwałeś swój plik :) ).
Będzie tam już trochę tekstu, ale nie jest nam potrzebny więc go w całości kasujemy. Teraz doprowadzamy zawartość pliku do takiej mniej więcej formy:



„Table Layout” to tabelaryczny układ elementów na ekranie aktywności , coś jak w HTML. Kolejne „TableRow” to po prostu kolejne wiersze w tabeli. Elementy zawarte w elemencie „TableRow” będą ze sobą sąsiadować w ramach danego poziomu w tabeli. Mamy tutaj dwa elementy: ImageView, oraz TextView. Pierwszy służy do wyświetlania obrazków, drugi do wyświetlania (ale nie wprowadzania) tekstu. W obu mamy parametr android:id. Nadajemy nim unikalną nazwę elementowi w ramach danej aktywności. Wartość tego parametru musi się zaczynać od „@+id/” po których następuje nasz identyfikator. Ten identyfikator jest niezbędny do rozróżniania elementów i jednoznacznego wskazywania jednego z nich. W obu też występują parametry layout_width i layout_height. Określają one szerokość i wysokość elementu. Jednostka DP to piksele niezależne od rozdzielczości ekranu. W elemencie ImageView jest jeszcze parametr android:src. Poprzez niego podajemy jaki obrazek ma zostać wyświetlony. Jeśli chodzi o obrazek zawarty w projecie (a nie znajdujący się np. na zdalnym serwerze czy karcie pamięci) to zaczynamy wartość od „@drawable/” po którym następuje nazwa obrazka wrzuconego w jednym z poprzednich kroków do katalogu drawable-hdpi. Nie podajemy rozszerzenia (tutaj .png) w nazwie pliku.
W elemencie TextView mamy dodatkowo element android:text przy użyciu którego ustawiamy tekst jaki ma być wyświetlany na elemencie. Związany z nim jest jeszcze element android:textSize, który określa wielkość czcionki. Użyłem tutaj też parametrów android:layout_marginLeft, oraz android:layout_marginTop. Określają one margines lewy , oraz górny.
Wracamy do widoku projektowania graficznego. Nasza aplikacja powinna w tej chwili wyglądać mniej więcej tak:


Dodałem analogicznie kolejne wiersze tabeli z kolejnymi elementami. Zmieniłem też wielkość czcionki na 20dp ponieważ niektóre opisy nie mieściły się w jednej linii:


Po tym zabiegu program wygląda tak:



Przyszła pora na dodanie nowej aktywności – tj. ekranu na który aplikacja powinna przejść po kliknięciu na napis „pole kwadratu”. Klikam prawym przyciskiem myszy na pakiecie w którym znajduje się moja pierwsza aktywność i wybieram NEW--> OTHER:




Dalej „Android Activity”:



Podobnie jak i wcześniej nadaje klasie aktywności i plikowi layoutu nazwy:


Klasa nowej aktywności:



Zauważ że w metodzie „onCreate” jest wywołanie metody setContentView, która służy do wiązania aktywności z opisem wyglądu zawartym w pliku XML. Każda aktywność domyślnie będzie miała swój plik xml i po stworzeniu będzie wywołanie jej własnego pliku, ale możesz do zmienić wskazując w parametrze inny layout. Tutaj mamy R.layout.activity_pole_kwadratu, ponieważ taki właśnie plik został utworzony podczas generowania nowej aktywności:



Domyślnie zawartość tego pliku wygląda tak:


Na ten moment ta aktywność będzie po prostu wyświetlała napis „Hello World!”. My w tej aktywności dodamy parę elementów, będzie to formularz do obliczania pola kwadratu. Przechodzimy do graficznej formy edycji layoutu:

Napis który już tam się znajduje nieco zmodyfikujemy. Klikamy nań prawym przyciskiem myszy i wybieramy „Edit Text”:



Wcześniej tekst wpisywaliśmy niejako „bezpośrednio”, teraz przyjmiemy nieco inną konwencję. W projekcie obecny jest plik strings.xml:


Znajdują się w nim identyfikatory, oraz przypisane do nich teksty. Chcąc wyświetlić jakiś tekst na elemencie, będziemy się odwoływać poprzez identyfikator do tekstu zawartego w tym pliku.

Po co nam to wszystko? Dzięki temu mamy wszystkie informacje tektstowe w jednym miejscu, dużo łatwiej jest je dzięki temu zmieniać. Ponadto znacznie łatwiej będzie później robić różne wersje językowe naszego programu, bo wystarczy potem tylko podmienić ten jeden plik. Ustawimy teraz napis na TextView, jednocześnie dodając go do pliku strings.xml:


Wybieramy edycję i przechodzimy do takiego ekranu:


Klikamy przycisk „New String”. Powinniśmy teraz zobaczyć taki ekran:


W polu „String” wpisujemy tekst który ma zostać dodany do pliku strings.xml. Oraz wyświetlony na komponencie. W polu „New R.string” podajemy identyfikator tekstu, pod który zostanie wpisany tekst do pliku.




Zatwierdzamy. Zobaczymy taki ekran:


Pojawi się nowy wpis w pliku strings.xml, a napis na komponencie się zmieni:

Dobrze. Mamy teraz ekran początkowy z listą elementów do wyboru, oraz zalążek nowego ekranu który docelowo będzie służył obliczaniu pola kwadratu. Trzeba teraz te elementy połączyć. Po kliknięciu napisu „pole kwadratu” na naszej aplikacji powinna pojawić się aktywność do obliczania pola kwadratu. Przyszedł czas na dodanie reakcji na kliknięcie napisu.


Zmieniłem nieco zawartość klasy mojej głównej aktywności. Dodałem zmienną t1 która będzie reprezentowała komponent TextView z napisem „Pole kwadratu”. W linii 19 do tej zmiennej przypinam realny komponent. Robię to przy użyciu wbudowanej metody findViewById. Ma ją każda klasa dziedzicząca po Activity. Ta metoda służy do zwracania referencji komponentu z aktywności. Do zmiennej t1 zostaje przypisany element o identyfikatorze textView1 (czyli nasz napis „pole kwadratu” z ekranu głównego:



Obsługę zdarzenia kliknięcia realizujemy poprzez podstawienie listenera dla obiektu t1. Listener to taki proces nasłuchu który czeka na jakieś zdarzenie. Tworzymy nasz listener jako obiekt klasy OnClickListener i jednocześnie defuniujemy dla niego reakcję na kliknięcie (metoda onClick). Tymczasowo reakcja na kliknięcie komponentu ma polegać na zmianie napisu „Pole kwadratu na napis „AŁA!!!!”. Stworzony listener ustawiamy dla obiektu t1 poprzez metodę tego obiektu setOnClickListener.

Uruchamiam projekt i sprawdzam działanie. Reakcja na kliknięcie jest taka jaka być powinna. Nasz program jest nadwrażliwą beksą :)


Skoro już działa obsługa kliknięcia, to teraz jako reakcję wepniemy uruchomienie innej aktywności w miejsce zmiany tekstu.

Wykomentowałem zmianę tekstu. Dodałem obiekt klasy Context do którego w linii 28 przypisuję kontekst aplikacji. W linii 29 tworzę nową intencję. Intencje to komunikaty łączące ze sobą różne komponenty.W tym przypadku nasza intencja będzie służyła wywołaniu innej aktywności. W tej samej linii podaję też informację, aktywność jakiej klasy ma zostać wywołana. W linii 30 odpalam tę aktywność.
Sprawdzam działanie całości. Tym razem po kliknięciu napisu „Pole kwadratu” nie zmienia się tekst na komponencie, a zostaje wyświetlony ten ekran:



Skoro wywołania działają, trzeba przerobić tę aktywność tak, aby faktycznie służyła obliczaniu pola kwadratu. Przechodzę więc do pliku layoutu tej aktywności:


by następnie w trybie projektowania graficznego poprzyklejać do niej niezbędne komponenty.




Pojawiły się tu nowe rzeczy. Komponent klasy Button, komponent klasy LargeText, oraz komponent klasy EditText. Button to po prostu przycisk. LargeText to element wyświetlający tekst, ale o powiększonej czcionce. EditText to komponent w którym możemy wyświetlić jakiś tekst, ale użytkownik programu będzie mógł gozmienić.

Po rozmieszczeniu elementów przechodzimy do edycji klasy aktywności :


W analogiczny sposób jak dla kliknięcia napisu „Pole kwadratu” oprogramowałem tutaj kliknięcie przycisku z napisem „Oblicz”. Zdefiniowałem w liniach 14-16 obiekty które będą reprezentować używane przeze mnie komponenty. W liniach 23-25 przypisuję do tych obiektów referencje do komponentów. W liniach 27-36 mam oprogramowaną reakcję na kliknięcie przycisku. Działa to analogicznie jak wcześniejszy przykład. Z nowości jest tutaj tylko rodzaj reakcji. W liniach 31-33 jest opisane co dokładnie ma się zdarzyć. Generalnie ustawiam tekst na komponencie wynik (to ten komponent klasy LargeText który ma domyślnie ustawione trzy myślniki. Ustawiany tekst to kwadrat wartości podanej poprzez obiekt bok – czyli obiekt klasy EditText, do którego użytkownik wprowadzi długość boku kwadratu. Po drodze pojawiają się też rzutowania z tekstu na liczbę i odwrotnie :)



Po wprowadzeniu długości boku i kliknięciu przycisku „Oblicz” mamy taki efekt:



W charakterze ćwiczenia, dokończ niniejszy projekt, może przyda się młodszemu rodzeństwu :)

9 komentarzy:

  1. Może wprowadzenie do obsługi błędów, np. co jeśli zamiast liczb wpiszemy litery?

    OdpowiedzUsuń
    Odpowiedzi
    1. No to możesz sobie ustawić te pole w które wpisujesz długość boku, że przyjmuje tylko wartości liczbowe. W pliku xml będzie to wartość android:inputType="number" i wtedy nie będziesz miał możliwości wpisania czegokolwiek innego niż liczby ;)

      Usuń
    2. Przy typie number nie wpiszemy też kropki i przecinka, a zatem nie wpiszemy liczby rzeczywistej ;)

      Usuń
    3. Polecam:
      android:inputType="numberDecimal|numberSigned"

      Usuń
  2. A obsługa błędu przy toast, jeżeli edittext będzie null?

    OdpowiedzUsuń
  3. Linijkę, gdzie liczone jest pole kwadratu można było zrobić za pomocą potęgi, używając operatora Math.pow(liczba podnoszona do potęgi, wykładnik potęgi):
    wynik.setText(Math.pow(Double.parseDouble(bok.getText().toString()), 2)+"");

    OdpowiedzUsuń
  4. Jak zmienic nazwe polekwadratu jesli juz jest utworzone polekwadratuactivity. wyswietla sie to dalej. uzylem opcji refactor i zmienilem nazwe classy ale dalej to activity sie pojavia mimo ze w glownej clasie juz tego niemam i w pozostalych

    OdpowiedzUsuń
    Odpowiedzi
    1. ok. znalezione w pliku strings.xml folder res podfolder values. Polecam przejsc kurs od a do z tego pana.Pozdro

      Usuń
  5. W którym miejscu i jak podpiąć kolejne aktywnosci do przejscia na kolejny ekran?

    OdpowiedzUsuń