Programování pro iOS - 30. Rotace zařízení - MujMAC.cz - Apple, Mac OS X, Apple iPod

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:

Soutěž

Sponzorem soutěže je:

IDIF

 

Kde se narodil známý fotograf František Drtikol?

V dnešní soutěži hrajeme o:

Seriály

Více seriálů



Software

Programování pro iOS - 30. Rotace zařízení

23. února 2011, 00.00 | Dnes se soustředíme na služby podporující změny zobrazení při rotaci: jak každý uživatel ví, u zařízení s operačním systémem iOS je poměrně běžné, že bez ohledu na to, jak zařízení natočíme, zůstává grafické uživatelské rozhraní "hlavou nahoru".

Chceme-li podporovat změnu zobrazení při rotaci – což je na iPadu prakticky povinné, zatímco na kapesních zařízeních hodně záleží na konkrétním typu aplikace –, je zapotřebí implementovat minimálně jednu speciální metodu v každém řídicím objektu, jehož rámce mohou být zobrazeny jak na šířku, tak i na výšku.

Před změnou orientace knihovní kód pošle aktivnímu řídicímu objektu rámce zprávu shouldAutorotateToInterfaceOrientation:-(BOOL)shouldAutorotateToInterfaceOrientation:
       (UIInterfaceOrientation)interfaceOrientation

kde argument interfaceOrientation obsahuje "budoucí" orientaci zařízení, tj. tu, pro niž by se mělo zobrazení rámců adekvátně změnit. Možné hodnoty jsou

UIInterfaceOrientationPortrait:

UIInterfaceOrientationPortraitUpsideDown:

UIInterfaceOrientationLandscapeLeft:

UIInterfaceOrientationLandscapeRight:

Vrátí-li metoda hodnotu YES, rámec adekvátně přerotuje; pokud vrátí NO, rámec zůstane beze změny.

Standardní implementace této metody ve třídě UIViewController vrací hodnotu YES pouze pro argument UIInterfaceOrientationPortrait; rotaci tedy efektivně zakazuje. Chceme-li ji podporovat, musíme metodu sami reimplementovat – nejspíše asi prostě takto:

-(BOOL)shouldAutorotateToInterfaceOrientation:
       (UIInterfaceOrientation)interfaceOrientation {
  return YES;
}

Vlastní rotace rámců

Při troše štěstí a šikovnosti s návrhem rámců může být výše uvedená implementace vše, co potřebujeme a nic jiného nemusí být vůbec nutné programovat. Poté, co metoda shouldAutorotateToInterfaceOrientation: vrátí hodnotu YES, totiž knihovní kód automaticky změní velikost i orientaci zobrazovaných rámců a ty se tedy automaticky překreslí odpovídajícím způsobem.

Pokud máme všude korektně nastaveny příznaky pro automatickou změnu velikosti – jde o přepínače ve stránce "Size" panelu inspektoru v Interface Builderu; seznámili jsme se s nimi už v odstavci "Autosizing" tohoto článku, kde jsme si také zdůraznili jejich důležitost – a pokud u našich vlastních rámců, kde implementujeme vlastní metodu drawRect:, tak činíme korektně, je docela slušná šance, že se vše správně překreslí "samo od sebe" a o nic dalšího se starat nemusíme.

Samozřejmě, zdaleka tomu tak není vždy: zvláště na iPhone, ale někdy i u iPadu, může být zapotřebí u odlišné orientace jednotlivé rámce přeskládat odlišným způsobem – to, co bylo nad sebou, položit vedle sebe, a podobně. Pak se samozřejmě musíme o tyto změny postarat explicitně.

Knihovní kód třídy UIViewController nám k tomu nabízí následující metodu:

-(void)willAnimateRotationToInterfaceOrientation:
       (UIInterfaceOrientation)interfaceOrientation
       duration:(NSTimeInterval)duration;

Odpovídající zpráva se automaticky pošle každému řídicímu objektu viditelného rámce předtím, než se začne jeho obsah rotovat; argument interfaceOrientation přitom informuje o cílovém postavení, a obsahem argumentu duration je doba, již rotace zabere.

V rámci implementace této služby tedy můžeme provést všechny potřebné změny – např. přemístění rámců apod.

Pro nejlepší viditelný efekt bychom se navíc měli postarat o to, aby změny byly animované a aby jejich animace trvala právě duration sekund. My se v našem seriálu zatím animací rámců nezabývali; později ale uvidíme, že díky tomu, že rámce jsou v systému iOS postaveny "nad" vrstvami knihovny Core Animation, je to obecně opravdu velmi jednoduché.

Stejně dobře samozřejmě tuto metodu můžeme využít v případě, kdy sice nepotřebujeme měnit vzájemné rozložení rámců, ale chtěli bychom animaci rotace nějak upravit (např. v průběhu rotace rámce zatmavit apod.) – i tehdy prostě potřebné animace v rozsahu duration sekund spustíme z této metody.

Alternativně – pokud by to pro nás bylo pohodlnější – můžeme použít trojici metod, jež jsou tak trochu přežitkem z iOS 2, ale fungují dosud: jejich princip je týž, ale místo toho, aby se všechny animace aktivovaly najednou na počátku otáčení, je celá akce rozdělena do dvou samostatných kroků, a každý lze animovat samostatně: někdy to může být pohodlnější.

-(void)willAnimateFirstHalfOfRotationToInterfaceOrientation:
       (UIInterfaceOrientation)toInterfaceOrientation
       duration:(NSTimeInterval)duration;
-(void)didAnimateFirstHalfOfRotationToInterfaceOrientation:
       (UIInterfaceOrientation)toInterfaceOrientation;
-(void)willAnimateSecondHalfOfRotationFromInterfaceOrientation:
       (UIInterfaceOrientation)fromInterfaceOrientation
       duration:(NSTimeInterval)duration;

Obecně je ale kdykoli, když si s tím vystačíme, lepší použít novější "jednorázovou" variantu.

Příprava a ukončení rotace

Obsahují-li naše rámce i za běžných okolností nějaké animace, přehrávání videa a podobné služby, je většinou zapotřebí tyto dynamické záležitosti před rotací pozastavit a po ní opět spustit; jinak výsledek nevypadá příliš dobře.

K tomu se metoda willAnimateRotationToInterfaceOrientation:duration: příliš nehodí – ačkoli bychom samozřejmě mohli v její implementaci animace apod. pozastavit a naplánovat znovuspuštění po duration sekundách pomocí standardní služby performSelector:withObject:afterDelay:, nebylo by to ani praktické, ani elegantní, ani efektivní.

Třída UIViewController proto nabízí další dvojici služeb, určenou speciálně pro tyto případy – v implementaci metody

-(void)willRotateToInterfaceOrientation:
       (UIInterfaceOrientation)toInterfaceOrientation
       duration:(NSTimeInterval)duration;

pozastavíme všechny animace apod., a můžeme se spolehnout na to, že odpovídající zprávu dostaneme dříve, než rámce začnou rotovat. Pro reaktivaci služeb pak je určena metoda

-(void)didRotateFromInterfaceOrientation:
       (UIInterfaceOrientation)fromInterfaceOrientation;

– odpovídající zprávu nám pošle knihovní kód poté, co je rotace ukončena.

Aktuální poloha přístroje

Implementujeme-li správně výše popsané služby, je krajně nepravděpodobné, že bychom někdy potřebovali navíc zjišťovat aktuální polohu zařízení. Pokud by to ale přece nastalo, máme k dispozici atribut

@property(nonatomic,readonly)
        UIInterfaceOrientation interfaceOrientation;

jehož hodnota vždy odpovídá aktuální poloze.

Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » Informace  

 » Rubriky  » Agregator  

 » Rubriky  » Tipy a Triky  

 » Rubriky  » Začínáme s  

 » Rubriky  » Software  

Diskuse k článku

 

Vložit nový příspěvek   Sbalit příspěvky

 

Zatím nebyl uložen žádný příspěvek, buďte první.

 

 

Vložit nový příspěvek

Jméno:

Pohlaví:

,

E-mail:

Předmět:

Příspěvek:

 

Kontrola:

Do spodního pole opište z obrázku 5 znaků:

Kód pro ověření

 

 

 

 

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: