5. diel - PRIPOMIENKOVÉ narodenín pre MacOS - Dokončenie UI a prepojenie
V minulej lekcii, PRIPOMIENKOVÉ narodenín pre MacOS - Príprava UI , sme si vytvorili hlavné okno aplikácie a prepojili UI komponenty s kódom. Tým ale naša tvorba užívateľského rozhrania neskončila, pretože ešte potrebujeme druhé okno, kde bude užívateľ môcť osoby pridávať. Okno bude jednoduchšie, pretože nám bude stačiť iba zadať meno a pomocou špecializované komponenty vybrať dátum narodenia.
Okno pre pridanie osoby
Najskôr si teda vytvoríme druhé okno.
Vytvorenie modálneho okná
Otvoríme Main.storyboard
az knižnice komponentov pretiahneme
Window Controller
. Týmto vlastne získame to isté, čo sme mali
pri vytvorení projektu, teda okno a na neho naviazaný View Controller.
Mali by sme získať zhruba niečo takéto:
Pre väčšiu prehľadnosť upravíme oknám titulky. Prvému oknu nastavíme
titulok "BirthdayMinder" podľa názvu projektu, túto vlastnosť
Title
nájdete v Attributes inšpektorovi.
U druhého okna musíme upraviť Title
, avšak u View
Controlleru, pretože budeme druhé okno zobrazovať druhov dopravy štýlom,
teda ako dialóg. Tu ako Title
nastavíme "Pridať osobu".
Otvorenie modálneho okna
Ešte, než na druhé okno zasadíte nejaký ovocný komponenty, pripravíme si navigáciu, aby sme sa na neho vôbec mohli dostať. Možností je viac, my sa spoľahneme na jednoduché segue, podobne ako u iOS aplikácií.
Segue vytvoríme v Main.storyboard
pomocou ťahanie za držanie
Ctrl z View Controlleru prvého okna (toho hlavného) na View
Controller druhého okna. Odporúčam ťaženie vykonávať v Document outline
(teda v zozname komponentov v ľavej časti), aby ste mali istotu, že skutočne
ťaháte z View Controller.
Z ponuky vyberieme možnosť "Modal", ktorá spôsobí, že nové okno bude dočasne hlavným oknom aplikácie a na to prvé nepôjde do zatvorenia nového okna kliknúť. Tým dáme užívateľovi najavo, že musí dokončiť prácu s druhým oknom, aby mohol pokračovať. Postup pre vytvorenie segue si ukážme na animáciu:
Ak by ste chceli mať jednoducho len viac okien a užívateľa neobmedzovať, stačilo by zvoliť možnosť "Show".
Teraz potrebujeme vytvorené segue pomenovať, pretože s ním budeme
pracovať v kóde. Nové segue teda označíme a v Attributes inšpektorovi mu
nastavíme vlastnosť Identifier
na "AddPersonSegue".
Segue by bolo možné vytvoriť ťahaním priamo z tlačidla "Pridať" na druhý View Controller, čím by toto tlačidlo automaticky nové okno otvorilo. Manuálne spustenie segue je ale flexibilnejší, preto ho použijeme.
Dostávame sa do finále a konečne si okno otvoríme. Postačí k tomu jeden
riadok kódu. Otvoríme si ViewController.swift
a do metódy
addBtn_Clicked()
, ktorá slúži k obsluhe tlačidla Pridať,
doplníme nasledujúci kód:
performSegue(withIdentifier: "AddPersonSegue", sender: self)
Aplikáciu môžeme spustiť a vyskúšať:
Bohužiaľ okno sa nezobrazuje relatívne vzhľadom k tomu hlavnému. To nie
je niečo, čo by sa dalo v Main.storyboard
ľahko naklikať,
riešenie pomocou kódu si ukážeme neskôr.
Tvorba UI modálneho okna
Prázdne okno je nám celkom k ničomu, preto ho naplníme komponentmi.
Budeme potrebovať textové pole pre zadanie mena osoby, špeciálne komponent
Date Picker
pre výber dátumu narodenia a tlačidlo pre
potvrdenie.
Zatváranie okná riešiť nebudeme, k tomu má užívateľ systémové
tlačidlo. Ako bonus pridáme dvojicu Label
komponentov, aby
používateľ vedel, čo má zadať a vybrať. A konečne ešte pridáme
obrázok, ktorý sa bude meniť podľa nastaveného farebného téme MacOS,
ktorá systém podporuje od verzie Mojave.
Push Button
Trochu netradične začneme odspodu a pridáme Push Button
.
Pomocou AutoLayout mu nastavíme horizontálne zarovnanie a trebárs
15
bodov od spodného okraja okna. Ešte nastavíme fixné šírku
na 80
a nastavíme text "Pridať". Celkovo tak máme tri
constraints.
Hodí sa povedať, že práve táto tvorba UI je skôr odporúčania. Ak chcete experimentovať a máte lepší nápad, ako komponenty poskladať, tak určite smelo do toho
Date Picker
Nad tlačidlo pretiahneme z knižnice komponent Date Picker
.
Opäť ju zarovnáme horizontálne na stred a nastavíme spodné CONSTRAINT na
15
bodov, teda na 15
bodov od predtým pridaného
tlačidla. Predvolené nastavenie komponenty nám vyhovuje a nič nie je
potrebné meniť.
Text Field
Posledný z nutných komponentov je Text Field
, ktorý bude
slúžiť na vyplnenie mena osoby. Opäť mu nastavíme zarovnanie na
horizontálne stred, 15
bodov od spodnej hrany a fixné šírku
90
.
Aktuálne UI vyzerá zhruba takto:
Labely
Pridáme Label
komponenty, aby sme používateľovi pripomenuli,
čo má zadať. Komponentom nastavíme veľkosť fontu System Small a zarovnáme
vertikálne s komponentom, ku ktorej patrí.
Potom už bude stačiť nastaviť len odsadenie z pravej strany. Ja som
zvolil hodnotu 3
. To isté vykonáme pre Label
patriaci k Date Picker.
Obrázky pre svetlé i tmavé tému MacOS
Ako asi viete, MacOS od verzie Mojave ponúka možnosť zapnúť tmavé tému. A ak si nenastavíte vlastné farby komponentov, bude aplikácia vyzerať dobre v oboch prípadoch. Na tej našej to môžeme vyskúšať. Stačí v Xcode prepnúť "View as: Dark Appearance" na svetlé tému.
My chceme naše okno pre pridanie novej osoby doplniť obrázkom. Pretože sa jedná o jednofarebný obrázok, tak chceme, aby aplikácie pre každú tému použila iný. To sa dá veľmi ľahko zariadiť. Obe varianty obrázku nájdete v zdrojových súboroch k tejto lekcii.
Image Set
V prvom rade si otvoríme Assets.xcassets
a pomocou tlačidla
+
dole pridáme New Image Set
. Ten z východzieho
Image
premenujeme na Person
. Otvoríme si Attributes
inšpektor tohto obrázku a nájdeme položku Apperances
. Tá je v
predvolenom stave nastavená na None
. My vyberieme možnosť
Any, Dark
.
Hneď môžeme vidieť, že sa zmenili "kolónky" pre obrázky a máme možnosť pridať obrázok pre tmavé tému:
Zostáva presunúť obrázky:
A to je všetko! Teraz už stačí tento obrázok použiť a systém automaticky vyberie správny podľa nastaveného témy.
Vrátime sa do Main.storyboard
a dokončíme druhé okno.
Image View
Pridáme komponent Image View
pre zobrazovanie obrázkov a rovno
ju ako obrázok nastavíme Person
, ktorý sme si pripravili.
Stačí nastaviť AutoLayout a bude hotovo.
Image View
tradične zarovnáme horizontálne na stred,
nastavíme vzdialenosť 20
od hornej hrany, minimálne
15
od spodnej hrany (teda od textového poľa) a maximálnu výšku
na 150
. Opäť platí, že sa jedná o návrhy a môžete
samozrejme experimentovať.
Constraints pre obrázok vyzerajú takto:
A hotové druhé okno aplikácie:
Môžeme tiež vyskúšať, že fungujú správne obrázky:
Prepojenie UI a kódu
Užívateľské rozhranie druhého okna je hotové, teraz ho prepojíme s
kódom. Potrebujeme @IBOutlet
pre Text Field
a
Date Picker
. Pre tlačidlo Pridať vytvoríme
@IBAction
. Jedná sa o opakovanie, v
AddPersonViewController
by sme mali mať:
@IBOutlet var nameTextField: NSTextField! @IBOutlet var datePicker: NSDatePicker! @IBAction func confirmBtn_Clicked(_ sender: NSButton) { }
Komunikácia medzi oknami
Na záver tejto lekcie si obe okná prepojíme, aby sme v tej ďalšej mohli pohodlne začať pridávať osoby.
Prvým krokom je vytvorenie View Controlleru pre druhé okno. Nezabudnite pri
vytváraní súboru vybrať Cocoa Class a na ďalšej obrazovke nastaviť ako
subclass NSViewController
. Išlo by to aj ručne, ale tento spôsob
je rýchlejší. Ako názov zvolíme AddPersonViewController
. Pred
potvrdením skontrolujte, že nie je zaškrtnutá možnosť "Also create XIB
file for user interface". To nechceme.
Teraz musíme do Main.storyboard
a nastaviť novovytvorenú
triedu druhému View Controlleru v jeho Identity inšpektorovi:
Vrátime sa do AddPersonViewController
a pridáme si
nasledujúce vlastnosť:
weak var delegateVC: ViewController!
Možností, ako komunikovať medzi oknami, je nespočet. My si ukážeme jednoduchú z nich, inšpirovanú návrhovým vzorom delegát. Pomocou tejto vlastnosti získame prístup k View Controlleru hlavného okna a budeme ho môcť informovať o tom, že používateľ vyplnil údaje a chce pridať osobu. Samozrejme by sme tu mohli využiť protokol, ale my tvoríme jednoduchú aplikáciu.
Vlastnosť musí byť weak
, aby medzi oboma View
Controllery nevznikol retain cycle,
kedy sa objekty vlastné navzájom a nemôže preto dôjsť k ich
delokácia.
Vrátime sa do ViewController
a preťažíme metódu
prepare()
, ktorá je automaticky zavolaná tesne predtým, než
prebehne segue.
Jej kostra vyzerá takto:
override func prepare(for segue: NSStoryboardSegue, sender: Any?) { }
Tu zistíme, či ide o "AddPersonSegue"
a ak áno, tak z neho
získame cieľový View Controller, čo bude práve náš
AddPersonViewController
a nastavíme mu vlastnosť
delegateVC
, čím oba controllery prepojíme:
override func prepare(for segue: NSStoryboardSegue, sender: Any?) { if segue.identifier == "AddPersonSegue" { let addPersonVC = segue.destinationController as! AddPersonViewController addPersonVC.delegateVC = self } }
Vieme, akého typu má byť destinationController
, takže
použitie as!
je v poriadku a dáva zmysel. Potom už len
nastavíme vlastnosť delegateVC
.
Nášmu ViewController
ešte pridáme nasledujúce metódu, aby
sme mohli prepojenie ľahko otestovať:
func addPerson(name: String) { print("Adding: \(name)") }
Zostáva zamieriť do AddPersonViewController
a doplniť
provizórne kód tlačidla Pridať:
@IBAction func confirmBtn_Clicked(_ sender: NSButton) { delegateVC.addPerson(name: "Test") }
Aplikáciu môžete zapnúť a skontrolovať výpis konzoly v Xcode. Pomocou
addPerson()
metódy neskôr budeme osoby pridávať už naozaj.
Oprava pozície druhého okna
Na úplný záver si opravíme štartovaciu pozíciu druhého okna, ako máme
sľúbené. Využijeme na to preťaženú metódu viewDidAppear()
.
Nemôžeme použiť viewDidLoad()
, pretože v tomto štádiu ešte
nie je plne inicializovanej okno (aj keď k tomu názov zvádza) a nedostali by
sme sa k nemu.
Pre istotu nezabudneme tiež zavolať super.viewDidAppear()
.
Základná kostra metódy v AddPersonViewController
teda vyzerá
takto:
override func viewDidAppear() { super.viewDidAppear() }
Čo vlastne potrebujeme urobiť?
Najskôr získať pozíciu prvého okna, získať rámček druhého okna (kvôli rozmerom), vypočítať korektné pozíciu a nastaviť ju druhému oknu. Celá metóda bude vyzerať takto:
override func viewDidAppear() { super.viewDidAppear() let mainWindowFrame = delegateVC.view.window!.frame let addPersonFrame = view.window!.frame let yPosition = mainWindowFrame.midY - addPersonFrame.height / 2 let xPosition = mainWindowFrame.midX - addPersonFrame.width / 2 view.window!.setFrameOrigin(CGPoint(x: xPosition, y: yPosition)) }
MacOS počíta pozície od ľavého dolného rohu, zatiaľ čo iOS (v UIKit) od ľavého horného.
Pre korektné pozíciu teda zistíme strednej Y a X súradnice a od každej odpočítame polovicu šírky respektíve výšky, čím získame korektné pozíciu pre druhé okno.
Môžeme vyskúšať:
Týmto sme úspešne dokončili celé UI, prepojili okná medzi sebou a tiež sme vyriešili pozicovanie druhého okna. V nasledujúcej lekcii, PRIPOMIENKOVÉ narodenín pre MacOS - Table View a práca s dátumom , sprevádzkujeme pridávanie osôb a oživíme Table View.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 12x (114.77 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Swift