Hlavní navigace

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

Lukáš Marek

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?

31. 3. 2011 11:45

pavel (neregistrovaný)

Přesně tak. Abych si ušetřil psaní 100 řádků "idotského XML pseudo-kódu" musím napsat 500 řádků "nádherně přehledného java kódu", který dělá přesně to samé.

31. 3. 2011 11:56

JohnnieK (neregistrovaný)

Dle mého názoru se XML daleko lépe čte, a když si UI rozdělíte ještě na samostatné bloky, které pak poskládáte přes include a používáte styly, tak je rozhodně pohodlnější takové UI udržovat.

Když chci custom kontrolku, udělám si stejně layout v XML, a pak to kódem jenom oživím, aby měla to správné chování.

Pak se to dá opět vložit do XML layoutu a funguje to opravdu dobře a přehledně:

<com.mypackage­.MyCustomControl android:id=...
...
/>

Samozřejmě můžu nějaké věci generovat dynamicky,…



120na80.cz: Boreliózu nelze žádným testem prokázat

Boreliózu nelze žádným testem prokázat

Vitalia.cz: 7 originálních adventních kalendářů pro mlsné

7 originálních adventních kalendářů pro mlsné

120na80.cz: Rovnátka, která nejsou vidět

Rovnátka, která nejsou vidět

DigiZone.cz: R2B2 a Hybrid uzavřely partnerství

R2B2 a Hybrid uzavřely partnerství

Root.cz: Nová třída SD karet A1 s vysokým výkonem

Nová třída SD karet A1 s vysokým výkonem

Vitalia.cz: Potvrzeno: Pobyt v lese je skvělý na imunitu

Potvrzeno: Pobyt v lese je skvělý na imunitu

Měšec.cz: Za palivo zaplatíte mobilem (TEST)

Za palivo zaplatíte mobilem (TEST)

DigiZone.cz: Sat novinky: slovenská TV8 HD i ruský NTV Mir

Sat novinky: slovenská TV8 HD i ruský NTV Mir

DigiZone.cz: V Plzni odstartovalo Radio 1

V Plzni odstartovalo Radio 1

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Vitalia.cz: Pamlsková vyhláška bude platit jen na základkách

Pamlsková vyhláška bude platit jen na základkách

Podnikatel.cz: Chaos u EET pokračuje. Jsou tu další návrhy

Chaos u EET pokračuje. Jsou tu další návrhy

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

DigiZone.cz: Ohrozí Freedom TV přechodové sítě?

Ohrozí Freedom TV přechodové sítě?

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

Vitalia.cz: Test na HIV je zdarma i za pět set

Test na HIV je zdarma i za pět set

120na80.cz: Co všechno ovlivňuje ženskou plodnost?

Co všechno ovlivňuje ženskou plodnost?

DigiZone.cz: Česká televize mění schéma ČT :D

Česká televize mění schéma ČT :D

Podnikatel.cz: Vládu obejde, kvůli EET rovnou do sněmovny

Vládu obejde, kvůli EET rovnou do sněmovny

Podnikatel.cz: Podnikatelům dorazí varování od BSA

Podnikatelům dorazí varování od BSA