W tej lekcji:
- Tworzenie układu liniowego
- Dodawanie pola tekstowego
- Dodawanie zasobów łańcuchowych
- Dodawanie przycisków
- Tworzenie pól tekstowych o szerokości ekranu
Do przeczytania:
Budowa graficznego interfejsu użytkownika aplikacji Android opiera się na hierarchii obiektów View i ViewGroup. Obiekty View
są zazwyczaj widocznymi elementami interfejsu, np. przyciskami i polami tekstowymi, natomiast obiekty ViewGroup
to niewidoczne kontenery określające sposób rozmieszczenia elementów widoków potomnych, np. w siatce albo pionowej liście.
Dostępna jest składnia XML odpowiadająca podklasom klas View
i ViewGroup
, dzięki czemu interfejs użytkownika można zdefiniować przy użyciu hierarchii elementów XML.
Alternatywne układy
Możliwość definiowania układu interfejsu użytkownika przy użyciu XML-a zamiast kodu programistycznego jest korzystne z kilku powodów, z których najważniejszym jest możliwość tworzenia różnych układów dla ekranów o różnych rozmiarach. Można na przykład utworzyć dwie wersje układu i nakazać systemowi stosowanie jednego na „małych” ekranach, a drugiego — na „dużych”. Więcej informacji na ten temat znajduje się w lekcji o obsłudze różnych urządzeń.

W tej lekcji dowiesz się, jak utworzyć przy użyciu XML-a układ zawierający pole tekstowe i przycisk. W następnej lekcji dowiesz się, jak reagować na naciśnięcie tego przycisku poprzez wysłanie zawartości pola tekstowego do innej aktywności.
Tworzenie układu liniowego
Otwórz plik activity_main.xml znajdujący się w katalogu res/layout/.
Domyślnie dodany do projektu szablon BlankActivity zawiera plik activity_main.xml, który z kolei zawiera widok główny RelativeLayout
i widok potomny TextView
.
Najpierw usuń element <TextView>
, a następnie nazwę elementu <RelativeLayout>
zmień na <LinearLayout>
. Później dodaj atrybut android:orientation
i przypisz mu wartość "horizontal"
. Teraz cały kod powinien wyglądać następująco:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
</LinearLayout>
LinearLayout
to grupa widoków (podklasa klasy ViewGroup
) rozmieszczająca widoki potomne w pionie lub poziomie, zgodnie z ustawieniem atrybutu android:orientation
. Widoki potomne widoku LinearLayout
na ekranie są wyświetlane w kolejności zdefiniowania w pliku XML.
Dwa pozostałe atrybuty, android:layout_width
i android:layout_height
, są wymagane we wszystkich widokach i określają ich wymiary.
Ponieważ LinearLayout
to główny widok układu, powinien on wypełniać cały obszar dostępny aplikacji na ekranie . Aby tak było, należy szerokość i wysokość ustawić na "match_parent"
. Wartość ta oznacza, że widok powinien rozciągać się w poziomie i pionie na całą szerokość i wysokość widoku nadrzędnego.
Więcej informacji na temat własności układów można znaleźć w poradniku dotyczącym Układów.
Dodawanie pola tekstowego
Aby utworzyć pole tekstowe, należy w elemencie <LinearLayout>
utworzyć element <EditText>
.
Jak w przypadku każdego obiektu klasy View
, własności obiektu EditText
należy zdefiniować przy użyciu odpowiednich atrybutów XML. Poniżej przedstawione jest poprawne umiejscowienie tego kodu w elemencie <LinearLayout>
:
<EditText android:id="@+id/edit_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/edit_message" />
Opis atrybutów:
android:id
Unikalny identyfikator dla widoku, przy użyciu którego można odnosić się do tego obiektu w kodzie aplikacji, np. aby odczytać ten obiekt i nim manipulować (przeczytasz o tym w następnej lekcji).
Znak @ jest wymagany zawsze, gdy odnosimy się do obiektu zasobu wewnątrz pliku XML. Po nim powinny znajdować się typ zasobu (w tym przypadku
id
), ukośnik oraz nazwa zasobu (edit_message
).Znak + przed typem zasobu jest wymagany tylko przy pierwszej definicji identyfikatora zasobu. Podczas kompilacji programu, narzędzia SDK używają tego identyfikatora do utworzenia nowego identyfikatora zasobu w pliku gen/R.java projektu, który odnosi się do elementu
EditText
. Po zadeklarowaniu identyfikatora zasobu w ten sposób, w kolejnych odniesieniach do niego nie trzeba już używać znaku plusa. Znak plus jest wymagany tylko, gdy określany jest identyfikator nowego zasobu i nie jest potrzebny dla konkretnych zasobów, takich jak łańcuchy i układy. Więcej informacji na temat obiektów zasobów znajduje się w bocznej ramce.android:layout_width
iandroid:layout_height
- Zamiast określać konkretne wartości szerokości i wysokości, za pomocą wartości
"wrap_content"
można sprawić, że widok będzie dopasowywał się rozmiarem do treści. Gdyby zamiast tego użyto wartości"match_parent"
, wówczas elementEditText
wypełniałby ekran, ponieważ byłby dopasowany rozmiarem do wymiarów rodzica, którym jestLinearLayout
. Więcej informacji na temat własności układów można znaleźć w poradniku dotyczącym układów. android:hint
Jest to domyślny tekst wyświetlany, gdy pole tekstowe jest puste. Zamiast konkretnego tekstu można wpisać wartość
"@string/edit_message"
odnoszącą się do zasobu łańcuchowego znajdującego się w osobnym pliku. Ponieważ odwołanie jest do konkretnego zasobu (nie identyfikatora), nie trzeba dodawać znaku plus. Ponieważ jednak wskazany zasób łańcuchowy nie jest jeszcze zdefiniowany, zostanie wyświetlone powiadomienie o błędzie. Wkrótce to naprawimy definiując ten łańcuch.
Dodawanie zasobów łańcuchowych
Tekst dodawany do interfejsu użytkownika zawsze powinien być definiowany w postaci zasobów łańcuchowych. Dzięki temu wszystkimi tekstami używanymi w interfejsie można zarządzać w jednym miejscu, co ułatwia pracę i modyfikowanie programu. Ponadto umieszczenie łańcuchów tekstowych na zewnątrz aplikacji umożliwia jej lokalizację w różnych językach polegającą na podaniu alternatywnych definicji dla każdego zasobu łańcuchowego.
Domyślnie twój projekt Android zawiera plik zasobów łańcuchowych o nazwie res/values/strings.xml. Otwórz go i usuń z niego element <string>
o nazwie hello_world
. Następnie dodaj nowy element <string>
o nazwie edit_message
i w jego treści wpisz tekst Wpisz wiadomość
.
Dodatkowo, skoro już jesteś w tym pliku, wpisz łańcuch Wyślij
dla przycisku o nazwie button_send
, który wkrótce dodasz do projektu.
Teraz plik strings.xml powinien zawierać następujący kod:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">My First App</string>
<string name="edit_message">Enter a message</string>
<string name="button_send">Send</string>
<string name="menu_settings">Settings</string>
<string name="title_activity_main">MainActivity</string>
</resources>
Więcej informacji na temat sposobów wykorzystania zasobów łańcuchowych do lokalizacji programów znajdziesz w lekcji o obsłudze różnych urządzeń.
Dodawanie przycisków
Teraz w układzie bezpośrednio za elementem <EditText>
dodaj element <Button>
:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send" />
Wysokość i szerokość są ustawione na wrap_content
, dzięki czemu przycisk dopasowuje się rozmiarem do znajdującego się na nim tekstu. Przycisk ten nie musi mieć atrybutu android:id
, ponieważ nie będziemy się do niego odwoływać z kodu aktywności.
Tworzenie pól tekstowych o szerokości ekranu
Aktualnie elementy EditText
i Button
dopasowują się rozmiarami do znajdującej się w nich treści, jak widać na rysunku 2.

Rozwiązanie to jest dobre dla przycisku, ale nie dla pola tekstowego, w którym użytkownik może wpisywać teksty o różnej długości. Dlatego lepiej by było wypełnić nieużywaną cześć ekranu tym polem. Można to zrobić w układzie LinearLayout
przy użyciu własności wagi, którą definiuje się za pomocą atrybutu android:layout_weight
.
Wartość ta jest liczbą określającą, ile miejsca ma zająć każdy z widoków względem ilości miejsca zajętego przez widoki siostrzane. Jest to coś podobnego do przepisów na drinki: „2 części wódki, 1 część likieru kawowego” oznacza, że 2/3 drinka stanowi wódka. Jeśli na przykład jednemu widokowi zostanie przypisana waga 2, a drugiemu 1, to suma ich wyniesie 3, a zatem pierwszy widok będzie zajmował 2/3 dostępnej przestrzeni, natomiast drugi — resztę. Jeśli dodamy do tego trzeci widok i nadamy mu wagę 1, wówczas pierwszy widok (o wadze 2) będzie zajmował 1/2 dostępnej przestrzeni, natomiast pozostałe dwa widoki po 1/4.
Domyślnie każdy widok ma wagę 0, a więc jeśli przypisze się wagę wyższą od 0 tylko jednemu widokowi, zajmie on całą przestrzeń, jaka pozostanie dostępna po przydzieleniu każdemu widokowi miejsca, które jest przez niego wymagane. Aby zatem wypełnić pozostającą wolną przestrzeń elementem EditText
w naszym układzie, nadajemy mu wagę 1, a wagę przycisku pozostawiamy bez zmian.
<EditText
android:layout_weight="1"
... />
Aby poprawić wydajność układu, gdy określi się wagę, należy szerokość elementu EditText
zmienić na zero (0dp). Ustawienie szerokości na zero sprawia, że układ jest bardziej wydajny, ponieważ wartość wrap_content
określająca szerokość zmusza system do obliczania szerokości, co jest niepotrzebne, gdyż później i tak waga zmusza go po raz kolejny do obliczenia szerokości elementu mającego wypełniać pozostającą wolną przestrzeń.
<EditText
android:layout_weight="1"
android:layout_width="0dp"
... />
Na rysunku 3. przedstawiono efekt przypisania wagi elementowi EditText
.

Poniżej przedstawiony jest kod, który powinien znajdować się w pliku układu:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<EditText android:id="@+id/edit_message"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/edit_message" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/button_send" />
</LinearLayout>
Układ ten jest stosowany przez domyślną klasę Activity
wygenerowaną przez narzędzia SDK podczas tworzenia projektu. Dzięki temu można już uruchomić aplikację, aby zobaczyć, jak działa:
- W Eclipse kliknij przycisk Start na pasku narzędzi.
W wierszu poleceń przejdź do katalogu głównego projektu i wykonaj następujące polecenie:
ant debug adb install bin/MyFirstApp-debug.apk
W następnej lekcji nauczysz się reagować na zdarzenia naciśnięcia przycisków, odczytywać tekst z pól tekstowych, rozpoczynać nowe aktywności i wiele więcej.
Witam,
Mam problem, nie moge uruchomić programu, gdyż wyskakuje błąd w pliku MainActivity.java , konkretnie w linijce:
.add(R.id.container, new PlaceholderFragment()).commit();
„container cannot be resolved or is not a field”.
W innej aplikacji jest ydentyczny kod i wszystklo jest ok.
Nadmienię, że przed tym, musiałam edytować plik fragment_main.xml, gdyż wyskakiwał mi błąd w linijce:
android:text=”@string/hello_world” />
hello_world zamieniłam na edit_message i juz było ok.
chyba że tutaj coś sknociłam.
Bardzo bym prosiła o pomoc.
A tak przy okazji, fajny kurs, pierwszy na jaki natrafiłąm, w którym wyjaśniane jest wszystko krok po kroku 🙂
Udało mi sie rozwiązać problem, w pliku activity_main.xml w wierszu: <EditText android:id="@+id/edit_message" zamiast edit_message wpisałam container i poszło.
Teraz tylko nie moge uruchomić aplikacji na tablecie, wyskakuje na urządzeniu info, że apliakcja została zatrzymana… ???