Lekce 3 - Swift UI pro různé displeje a Autolayout
V minulé lekci, Tvorba UI a seznámení se základními komponentami, jsme si vytvořili svou první Swift aplikaci v Xcode. Uměla ovšem pouze zobrazit textový popisek nebo některý z dalších ovládacích prvků Apple, které jsme si minule popsali.
V dnešním tutoriálu si ukážeme důležitou součást tvorby UI a sice, jak zajistit, aby byly komponenty na displeji přesně tam, kde je chceme.
Pravděpodobně víte, že moderní weby dnes počítají s tím, že uživatelé mají různé displeje (desktop, tablet, mobil..) a podle toho se přizpůsobují. U iOS situace není tak extrémní, ale pořád tu máme dvě velikosti iPhone (+ nový model X), několik iPadů a relevantní model je stále iPhone SE (rozměrově stejný jako model 5 a 5S). Velikostí displeje je i tak již mnoho a měli bychom s nimi počítat.
Práci si můžeme usnadnit určením aplikace pouze pro iPhone, přeci jen podíl iPadu není tak velký, ale přesto musíme počítat s různými displeji. Takže jak na to? Odpověď se jmenuje Autolayout, což je způsob, jak definovat UI, aby se přizpůsobilo displeji.
Layouty
Kdyby měla všechna zařízení stejně velké displeje, mohli bychom komponenty umisťovat jednoduše na přesné souřadnice (např. vložit popisek 20 pixelů na ose X a 40 pixelů na ose Y). Jakmile se ovšem fyzická velikost zařízení liší, musíme ovládací prvky na controlleru vždy přeskládat tak, aby se na displej všechny vešly nebo aby naopak nevyžívaly jen malou část. Přesně tento mechanismus nám layouty přináší.
Autolayout
Prvním z layoutů, které si představíme, je Autolayout
.
Pozice prvků v Autolayout určují tzv. constraints, což by
se do češtiny dalo přeložit jako omezení. V některých programovacích
jazycích je používán pojem kotva (anchor), protože constraints často
slouží k přichycení nějaké strany komponenty ke straně kontejneru, ve
kterém je vložená. V textu budu používat pojem constraints, protože mi
přijde výstižnější a navíc budete znát korektní anglický termín.
Aby Autolayout
fungovat korektně, musí mít každá komponenta
přesně určeno, jak má být umístěna vzhledem k dalším komponentám nebo
okrajům UI daného controlleru. Existuje více možností jak toho docílit.
Komponentu můžeme jednoduše zarovnat na obou osách, definovat ji vzdálenost
od okraje jiného UI prvku a tak podobně. Vše si podrobně ukážeme. V
různých situacích se hodí různé přístupy.
Autolayout
může být pro začátečníky
náročný, stále se ale jedná o jedinou rozumnou cestu, jak UI navrhovat,
takže se mu nevyhýbejte a nevzdávejte použití Autolayout po několika
nezdařených pokusech.
Praktická ukázka
Otevřeme Main.storyboard
, klidně v tom samém projektu s
Label
em z minulé lekce. Případně můžete založit nový
projekt a nějaké UI komponenty do něj přidat. Je to jedno, pracovat budeme
pouze v tomto jednom souboru. Označme si např. Label
a zarovnejme
ho na střed pomocí constraints. K tomu slouží ikonky v pravém dolním rohu
editoru.

Zarovnání komponenty
Prostřední ikonka Align constraints se dvěma obdélníčky slouží právě k zarovnání.

Zaškrtněme Vertically in Container a Horizontally in
Container, čímž Label
vycentrujeme v obou směrech. Pak
již stačí jen kliknout na Add 2 Constraints, čímž se k němu
příslušná zarovnávací omezení nastaví. Pojmem container se myslí
komponenta, ve které je prvek vložený. V tomto případě je myšlen celý
controller. Pokud byste Label
měli např. uvnitř komponenty
View
, která se často používá právě jako container ostatních
prvků nebo třeba na zaznamenání dotykových gest, tak container bude právě
tento View
. Tímto je Label
zarovnaný a na všech
displejích bude uprostřed. Jeho skutečná pozice (X a Y) se bude tedy měnit
podle velikosti displeje daného zařízení.
Výsledek:

Zajímá vás, proč jsme mohli zadat také konkrétní číslo a ve
výchozím stavu to byla 0
? To je pro případ, že bychom
Label
chtěli od středu posunout na libovolnou stranu. Např. o
několik pixelů vertikálně nad střed. Již přidané constraints si můžete
zkusit editovat v Size inspektoru. Protože se souřadnice počítají od
levého horního rohu, náš Label
bychom posunuli nahoru např.
nastavením constraint pro Y osu na -30
.
Připnutí ke stranám a omezení velikosti
Align constraints se hodí zejména k centrování. Nyní si ukážeme
constrainty na pozici a velikost. Zde již platí, že musíte mít nastavené
buď constraints pro všechny čtyři strany nebo dvě strany + šířku a
výšku komponenty. (Abych byl kompletní, tak výšce se můžete vyhnout
přes Aspect ratio.) Jedině tak bude Autolayout
přesně
vědět, kam komponentu umístit a jakou velikost ji nastavit. Samozřejmě
nemůžete mít nastavené např. constraints pro levou a pravou stranu a
zároveň nastavit fixní šířku. Tyto constrains budou mezi sebou v
konfliktu, protože přichycením obou stran komponenty ke kontejneru se
komponenta bude samozřejmě s kontejnerem roztahovat do šířky.
Zkusíme si nyní náš Label
umístit do pravého horního
rohu. Označte ho a následně klikněte na ikonku vedle té zarovnávací,
která vypadá trochu jako Tie Fighter.

Tento dialog již vypadá komplikovaněji, ale není se čeho děsit. Chceme pravý horní roh, takže budeme zarovnávat od horní a pravé hrany. Doporučuji odškrtnout Constrain to margins, které počítá od jakýchsi vnitřních hran a občas nefunguje korektně. Osobně se mi často stává, že tyto margins nejsou registrovány a navíc, když je nikdy nebudete používat, nestane se vám, že byste se spletli v rozměrech apod.
Label
umístíme např. 40
pixelů od horní hrany
a 40
pixelů od pravé. To, že je constraint aktivní poznáte
podle nepřerušované červené čáry. Po kliknutí se aktivuje/deaktivuje a
stejně tak jej aktivuje zadání nové hodnoty. Protože jsme
Label
ukotvili k horní a pravé hraně, nezapomeňte nastavit i
šířku a výšku, jinak by nebyla jeho velikost definována. Poté již
stačí jen kliknout na Add 4 Constraints a Label
jsme
úspěšně ukotvili. V pravém horním rohu nyní zůstane. Vyzkoušet to
můžete proklikáním různých displejů - přepínač je v dolní části
editoru.

Tímto jsme dva základní přístupy probrali, tím Autolayout
ovšem zdaleka nekončí.
Více komponent
Jakmile máme v kontejneru více komponent, Autolayout
je při
tvorbě constraints zohlední. Pokud bychom nyní k našemu Label
u
v pravém horním rohu přidali na jeho levou stranu další komponentu, např.
tlačítko Button
, constraint vzdálenosti pro pravou hranu
tlačítka se bude počítat od Label
u, což davá smysl. Můžete
si ale zvolit, aby se opět počítal od hrany controlleru (šipka dolů v
poli pro hodnotu). To ale nedoporučuji.
Než takto začnete nastavovat constraints více prvkům, vyplatí se
zapřemýšlet, jak má výsledek vypadat a jestli třeba nebudete v brzké
době přidávat komponenty nebo měnit jejich umístění. Nebojte se
využívat obyčejný View
jako kontejner pro komponenty, které
patří k sobě. Constraints pak budete nastavovat od hran tohoto
View
a ten samotný pak snadno posunete. Klidně jednotlivým
View
dočasně nastavte výrazné barvy pozadí, ať máte
přehled, jak jsou umístěny.
Konflikt mezi constraints
Občas se vám stane, že Autolayout
začne "nadávat",
protože mu constraints nesedí. Tehdy jste buď zapomněli nastavit vše
vyžadované nebo omylem přidali duplicitní constraint. Button
např. nemůže být 0
od levého okraje a zároveň jiným
constraintem nastaven na 20
taktéž od levého okraje. Xcode vám
poměrně dobře ukáže, kde je problém a umožní opravu "jedním
klikem". Osobně tyto jednoduché opravy nevyužívám, protože často
skončí jinak, než bych si přál. Stejně tak velmi zřídka používám
Reset to suggested constraints, které constraints určí za vás.
Třeba vám tyto možnosti vyhovovat budou, stačí je vyzkoušet.
Připomínám, že constraints najdete v Size inspektoru jednotlivých
komponent.
V příští lekci, Jednoduchá kalkulačka pro iOS ve Swift, se podíváme konečně na něco praktického a
vytvoříme jednoduchou iOS kalkulačku. S ní se naučíme používat
StackView
a propojit UI s kódem.