Kurs Android

Podstawowe layouty

W tym artykule przyjrzymy sie bliżej podstawowym layoutom:

 

  1. Linear Layout (Horizontal)
  2. Linear Layout (Vertical)
  3. Relative layout
  4. Frame Layout

Jak już zapewne sami zaważyliście pliki z layoutem można otwierać na co najmniej dwa sposoby. Pierwszym, edytorem wizualnym, posługiwaliśmy sie ostatnio. Pora na drugi. Otwórzmy sobie nasz plik z poprzedniej lekcji wybierając tryb xml.

Powinniśmy zobaczyć coś takiego:

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >

    <TextView
        android:id="@+id/nazwa"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/javastart"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <TextView
        android:id="@+id/imie_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/imie" />

    <EditText
        android:id="@+id/imie"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPersonName" >

        <requestFocus />
    </EditText>

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/plec" />

    <RadioGroup
        android:id="@+id/plec"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >

        <RadioButton
            android:id="@+id/radio0"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:checked="true"
            android:text="@string/kobieta" />

        <RadioButton
            android:id="@+id/radio1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/mezczyzna" />
</RadioGroup>

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/ocena" />

    <RatingBar
        android:id="@+id/ocena"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:numStars="5" />

    <Button
        android:id="@+id/przycisk"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:text="@string/ok" />

</LinearLayout>

 

Jak widać każdemu elementowi przypada kawałek odpowiadającemu mu kodu. Jest to dosyć czytelne, ponieważ dokładnie widać gdzie zaczyna się definiowanie parametrów danego elementu.

Niektórzy nie używają w ogóle trybu wizualnego, twierdząc, ze generuje on zbędny kod. Osobiście sie z nimi nie zgadzam. Kreator umożliwia w bardzo łatwy sposób stworzenie pożądanego layoutu.

Dzisiaj pokusimy sie o bardziej zaawansowany widok. W celu jego zrealizowania potrzebne będzie nam zrozumienie layoutów. Jeśli przejdziemy z powrotem do widoku wizualnego, to w wigetach możemy zauważyć zakładkę layout.

Samo przeciąganie layoutu na ekran właściwie nic nie daje, ponieważ jest to tylko pojemnik na właściwą zawartość. Zależnie od wybranego layoutu wrzucone w niego elementy będą układać sie z góry na dół, od prawej od lewej, albo będą zachowywały się zależnie od innego elementu. Ich istotna właściwością jest to, ze można wrzucać jeden layout do drugiego.

Linear Layout (Horizontal)

Elementy w tym layoucie będą się układać od lewej do prawej.

<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" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />

    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />

</LinearLayout>

Linear Layout (Vertical)

Elementy w tym layoucie będą się układać z góry na dół.

 

<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="vertical" >
.
.
.

</LinearLayout>

Jak widać, jedyna zmiana to dodatkowy atrybut android:orientation="vertical" dla LinearLayout.

Relative layout

Tutaj sprawa jest ciekawsza. Elementy układają się zależnie od innych elementów. Przyjrzyjmy się temu dokładniej.

Najpierw ustalmy RelativeLayout na całym ekranie - najlepiej skopiować poniższy kod.

<RelativeLayout 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" >

</RelativeLayout>

Przy przeciąganiu elementu pojawiają się strzałki wskazujące względem jakiego innego elementu zostanie on ustawiony. Ustawmy sobie kilka przycisków.

Zajrzyjmy teraz do tego co zostało wygenerowane w pliku XML.

<RelativeLayout 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" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="92dp"
        android:layout_marginTop="81dp"
        android:text="Button" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/button1"
        android:layout_below="@+id/button1"
        android:layout_marginTop="130dp"
        android:text="Button" />

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button1"
        android:layout_marginLeft="48dp"
        android:layout_marginTop="60dp"
        android:layout_toRightOf="@+id/button2"
        android:text="Button" />

</RelativeLayout>

Pojawiają się nowe atrybuty.

Te z informacją o odległości (zauważcie, że stosowanie jest dp, a nie px - informacja na ten temat na końcu artykułu)

android:layout_marginLeft   // dodatkowa odległość po lewej stronie

android:layout_marginTop   // dodatkowa odległość od góry

 

No i atrybuty relacyjne, wskazujące od których elementów zależą

android:layout_alignParentLeft  // zależne od lewej strony kontenera (layoutu) w którym się znajduje

android:layout_alignParentTop  // zależne od prawej strony kontenera (layoutu) w którym się znajduje

android:layout_below     // znajduje się pod wskazanym elementem

android:layout_toRightOf    // znajduje się po prawej stronie wskazanego elementu

 

Spróbuj teraz przemieścić pierwszy przycisk. Efekt - wszystko się przesunęło. Niestety nie ma na to lekarstwa i najlepszym sposobem zarządzania RelativeLayoutem jest wpisywanie go z poziomu XML.

 

Frame Layout

 

Używany dużo rzadziej niż inne layouty. Służy głównie do przechowywania tylko jednego widoku, który ma być widoczny nad innym.

 

 

 

<FrameLayout 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" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/tlo" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:text="Text na górze"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="#ff0000"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:text="Tekst na dole"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:textColor="#ff0000" />

</FrameLayout>

 

Tutaj nowym elementem może być ImageView. Jest to kontrolka służąca do wyświetlania grafik. Przed jej użyciem należy umieścić swój obrazek w forderze /res/drawable, a następnie wystarczy przeciągnąć kontrolkę ImageView na ekran, a system sam zapyta nas jakiej grafiki chcemy użyć. Wybieramy odpowiednią i gotowe.

Dodatkowe informacje

Przy projektowaniu ekranu należy zwrócić szczególną uwagę na to, że użytkownicy naszej aplikacji będą korzystali z niej na szerokiej gamie urządzeń z rożnymi rozdzielczościami. Dlatego właśnie w Androidzie nie stosujemy pikseli (px) tylko dp (Density-independent pixel).

Jego wielkość jest zależna od wielkości ekranu, co zapewnia nam, ze aplikacja będzie wyglądała niemal identycznie na wszystkich urządzeniach.

Pozostaje jeszcze kwestia zmiany orientacji ekranu. Tutaj sprawa nie jest taka prosta. Ja z reguły radze sobie w taki sposób, ze blokuje możliwość obrotu ekranu. Jest to podejście bardzo nieeleganckie. Optymalnym rozwiązaniem byłoby stworzenie osobnych layoutu dla orientacji pionowej i poziomej. Następnie wystarczy tylko przechwycić wydarzenie zmiany orientacji i wczytać alternatywny layout. Nie jestem jeszcze do końca przekonany co do takie podejścia. Postaram sie douczyć i w najbliższym czasie napisać o tym osobny artykuł.

Komentarze

Mateusz

" /res/drawabke" wkradła się literówka. Poza tym świetny artykuł :)

Marcin Kunert

Hej Mateusz, dzięki za info. Widzę, że uważnie czytałeś. Poprawiłem :)

Tomek

Świetne artykuły, jest jakaś konkretna częstotliwość z jaką je wrzucasz? Czy piszesz po prostu w wolnych chwilach?

Marcin Kunert

W wolnych chwilach, których ostatnio coraz mniej. Spróbuję się zmobilizować i coś niebawem dodać.

Lolo

Można jakoś napisać aplikację by nie miała okna ale, żeby można było np. wyświetlać toasty?