Programování pro Android: začátky s UI

Lukáš Marek 31. 3. 2011

Původním záměrem tohoto seriálu bylo sepsat pár tipů pro středně pokročilé androidisty. Živá diskuse pod prvním dílem ukázala, že se možná vyplatí „vrátit se ke kořenům“ a sepsat i pár tipů pro úplné začátečníky. Pořád ale platí, že články předpokládají alespoň slušně poučené čtenářské publikum.

Pokud jste úplní začátečníci a nevíte, jak si stáhnout a rozchodit Android SDK, budete si to muset nastudovat jinde.

Dnes se podíváme na vytváření uživatelského rozhraní Android aplikací.

Deklarativní GUI

Zřejmě kvůli co nejvyšší efektivitě využívá Android koncept tzv. deklarativního GUI. To znamená, že uživatelské rozhraní není vytvářeno kódem po jednotlivých krocích (jako je třeba Swing), ale každá obrazovka (nebo její část) je deklarována jako celek. Rozumíme si? Ne?

Prostě místo (pseudo)kódu:

  1. Vytvoř okno
  2. do okna vlož dialog
  3. do dialogu vlož text "Pozor"
  4. do dialogu vlož tlačítko "Ok"

se používá deklarace

  okno:
    obsahuje dialog:
      obsahuje text "Pozor"
      obsahuje tlačítko "Ok"

Deklarace jednotlivých obrazovek jsou napsány v XML (no flame, pls.) a uloženy v projektu v podadresáři res/layout. Při buildu aplikace se XML přeloží do úsporného binárního formátu, který je interpretován telefonem.

Je čas na první příklad. Úvodní obrazovka cvičné aplikace z minulého dílu je deklarována takto:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Zkus MENU -> Vyber kontakt"
    android:id="@+id/napoveda"
    />
</LinearLayout>

Jak je vidět, jde o velice jednoduchou obrazovku, ve které je do kontejneru LinearLayout vložen TextView. Všimněte si, že i délka a šířka jednotlivých prvků je určena relativně – buď má vyplnit celou velikost rodičovského prvku ( fill_parent), nebo má mít minimální potřebnou velikost ( wrap_content).

Atribut android:id slouží k pojmenování konkrétních prvků obrazovky a používá se jak k odkazování mezi jednotlivými prvky v XML, tak poté i v kódu.

Co se v Androidu dostupných prvků týká, jde v vcelku o standardní sadu: obrázek ( ImageView), text ( TextView), tlačítko ( Button) a tak podobně. Zde nezbývá než doporučit samostudium. Samozřejmě, že lze rozšířit nabízenou paletu i o vlastní tvorbu…

Opusťme samotné prvky a věnujme se něčemu zajímavějšímu – jejich rozložení na displeji.

Layouty

Podobně jako již zmíněný Swing, nemá Android moc rád absolutní pozicování prvků na displeji. Požadavek je to celkem logický, byť je díky tomu složitější dobrat se k pěkně vypadajícímu návrhu obrazovky.

A opět podobně jako u Swingu jsou programátorovi k dispozici kontejnery, zde nazývané layouty, které slouží k „rovnání“ jednotlivých komponent. Pojďme se podívat na nejpoužívanější:

LinearLayout

… aneb nejlepší kamarád každého začátečníka. Tento layout je nejvhodnější na učení, protože je relativně přímočarý. Jednoduše všechny do něj vložené prvky srovná do řady a to buď vertikálně ( android:orientation="vertical") nebo horizontálně ( android:orientation="horizontal").

Vzhledem k tomu, že layouty lze vkládat do sebe, dá se i s tímto jednoduchým prostředkem dosáhnout zajímavých výsledků. Bohužel za cenu toho, že vznikne dost rozsáhlý strom vnořených layoutů, což je navýsost nepřehledné pro programátora a výpočetně náročné pro mobil.

RelativeLayout

Z těchto důvodů většina začátečníků brzy přejde na RelativeLayout. Ten vložené prvky pozicuje relativně proti sobě. U prvku je tedy definováno, že je nad, pod nebo vedle nějakého jiného prvku. Pojďme si ukázat příklad:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="fill_parent" android:layout_width="fill_parent"
    android:layout_margin="10dip" android:gravity="fill_horizontal">

    <ImageView android:layout_height="50dip" android:src="@drawable/icon"
        android:layout_width="50dip" android:id="@+id/photo"
        android:layout_alignParentLeft="true" android:layout_margin="10dip"></ImageView>

    <LinearLayout android:layout_height="wrap_content"
        android:id="@+id/linearLayout1" android:layout_toRightOf="@+id/photo"
        android:layout_alignTop="@+id/photo" android:orientation="vertical"
        android:layout_width="fill_parent">

        <!-- 3 x TextView  -->

    </LinearLayout>

<RelativeLayout>

Zde je definována fotka kontaktu jako ImageView s id photo, který je „přilepen“ k levému okraji obrazovky ( android:layout_alignParentLeft="true") a má pevně definovanou šířku 50dip. No, a to, že LinearLayout, ve kterém jsou vloženy další kontaktní údaje, je vpravo od fotky, je zařízeno atributem  android:layout_toRightOf="@+id/photo".

Typicky se RelativeLayout používá pro základní rozvržení obrazovky, ostatní layouty pak pro pozicování jednotlivých skupin prvků.

ListView

Poslední ze skupiny častěji používaných layoutů je specialista na seznamy – ListView. Ten zobrazuje jednotlivé řádky, umožňuje jejich rolování, postupné načítání a podobné vymoženosti. ListView se používá relativně často a umí toho tolik, že by si zasloužil samostatný článek.

Ostatní layouty

Další nabízené layouty již nemají tak široké použití, nabízejí například rozložení prvků do tabulky ( TableLayout) nebo práci se záložkami ( TabLayout).

Nástroje pro tvorbu UI

Při pohledu na XML kód jednotlivých layoutů a hlavně při pohledu do nápovědy SDK na množství možných parametrů se nabízí otázka, zda neexistuje nějaká jednodušší cesta, než psát desítky XML tagů ručně.

Dobrá zpráva, existuje – Eclipse plugin pro Android obsahuje pěkný klikací editor obrazovek:


Špatná zpráva je, že je stejně nutné se alespoň základní atributy naučit a umět psát „ručně“, protože někdy je třeba editoru trochu pomoci. Většinou ale stačí přepnout se do zobrazení XML, opravit/přidat jeden konkrétní atribut (většinou android:layout_alignXX) a poté pokračovat v práci v „klikátku“.

UI v kódu

Pokud je obrazovka dokonale popsaná, nastává čas ji oživit. To už se dělá v kódu jednotlivých aktivit, zde například přímo v metodě  onCreate().

  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.empty);
    ((TextView) findViewById(R.id.napoveda)).setText("Ahoj svete");
  }

Co se tu děje? Metoda setContentView() najde deklaraci obrazovky res/layout/empty.xml a zobrazí ji na displeji. Konkrétně jde o příklad z první kapitoly.

Metoda findViewById() slouží k nalezení prvků podle id, které dostaly v deklarovaném XML. Samozřejmě, že id nemusí mít přiděleny všechny prvky, ale pouze ty, na které se v kódu bude odkazovat. Už méně samozřejmé je, že v různých XML souborech mohou být prvky se stejným id. To může zpřehlednit aplikaci – všechny prvky se stejným významem (např. tačítko OK) se tedy mohou jmenovat stejně.

DIP

Na závěr spíše poznámka pod čarou – rozměry prvků jsou často uváděny v jednotkách dip. To znamená density independent pixel a jak název napovídá, jde o jednotku, která se přizpůsobuje velikosti a rozlišení displeje. Takže obrázek o velikosti 100dip bude mít na všech telefonech zhruba stejnou relativní velikost.

Našli jste v článku chybu?
120na80.cz: Jak se zbavit nadměrného pocení?

Jak se zbavit nadměrného pocení?

Měšec.cz: Ceny PHM v Evropě. Finty na úspory

Ceny PHM v Evropě. Finty na úspory

Vitalia.cz: Taky je nosíte? Barefoot není pro každého

Taky je nosíte? Barefoot není pro každého

Měšec.cz: TEST: Vyzkoušeli jsme pražské taxikáře

TEST: Vyzkoušeli jsme pražské taxikáře

DigiZone.cz: CZ a SK Digi TV budou spolupracovat

CZ a SK Digi TV budou spolupracovat

Vitalia.cz: Nejdůležitější změny v potravinářské novele

Nejdůležitější změny v potravinářské novele

DigiZone.cz: Sat novinky: pátý kanál maďarské televize

Sat novinky: pátý kanál maďarské televize

Podnikatel.cz: Účtenky v rámci EET? Klidně emailem

Účtenky v rámci EET? Klidně emailem

Vitalia.cz: V dTestu vyhrál levný opalovací krém

V dTestu vyhrál levný opalovací krém

120na80.cz: I tuto vodu můžete pít

I tuto vodu můžete pít

Lupa.cz: Největší pitominy s logem “nyní smart a připojené”

Největší pitominy s logem “nyní smart a připojené”

Lupa.cz: Japonská invaze. Proč SoftBank kupuje ARM?

Japonská invaze. Proč SoftBank kupuje ARM?

DigiZone.cz: Sázka na e-sporty stanici Prima vychází

Sázka na e-sporty stanici Prima vychází

Vitalia.cz: Cvičení tabata: na hubnutí i posilování?

Cvičení tabata: na hubnutí i posilování?

Lupa.cz: Největší torrentový web KickassTorrents padl

Největší torrentový web KickassTorrents padl

Podnikatel.cz: Tahle praktika stála šmejdy přes milion

Tahle praktika stála šmejdy přes milion

Měšec.cz: Investice do drahých kovů - znáte základní chyby?

Investice do drahých kovů - znáte základní chyby?

Měšec.cz: Platíme NFC mobilem. Konečně to funguje!

Platíme NFC mobilem. Konečně to funguje!

Podnikatel.cz: Italské těstoviny nebyly k mání, tak je začal vyrábět

Italské těstoviny nebyly k mání, tak je začal vyrábět

Lupa.cz: Vodafone umí volání přes Wi-Fi. Z ciziny jako v ČR

Vodafone umí volání přes Wi-Fi. Z ciziny jako v ČR