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:
Začínáme s
Programování pro iOS - 17. Podpora standardních gest
24. listopadu 2010, 00.00 | Problémy s detekcí gest si naštěstí uvědomil samotný Apple. Od verze iOS 3.2 zahrnul do systému novou třídu UIGestureRecognizer: umožňující pohodlnou implementaci detekce gest nezávisle na rámci. Systém navíc standardně nabízí hotové rekognizery pro všechna standardní gesta.
V několika minulých dílech jsme si ukázali standardní podporu interpretace dotekového ovládání v iOSu, realizovaného prostřednictvím zpráv touches...:withEvent: na úrovni rámců nebo jejich řídicích objektů. Viděli jsme také, že už implementace poměrně jednoduchých gest – jako je třeba vícenásobné klepnutí – je poměrně komplikovaná. Složitá gesta více prsty se tak detekují velmi špatně.
Proto jsme si také v minulém dílu ukázali jen orientační implementaci gesta pro zoom: přímo toto gesto nebude zapotřebí implementovat už asi nikdy – iOS 3.1 je na samém konci životnosti (a dokonce i v něm většinu případů, kde bylo třeba detekovat gesto pro změny měřítka, pokryla standardní třída UIScrollView). Budeme-li tedy interpretovat složitá gesta více prstů, nebude to standardní "pinch zoom", ale speciální ovládání, výlučné pro tu kterou konkrétní aplikaci.
Rozhraní třídy UIGestureRecognizer
Pokud chceme služby tříd UIGestureRecognizer jen používat (a není třeba, abychom implementovali vlastní), je její rozhraní velmi jednoduché a pohodlné; v podstatě stačí jen
• instanci vhodné třídy vytvořit;
• případně nastavit atributy požadovaného gesta – je-li to v konkrétním případě zapotřebí;
• a připojit ji k rámci, v němž má gesta interpretovat.
Základní metody
K tomu slouží dvě standardní metody
-initWithTarget:(id)target action:(SEL)action;
Standardní (a také designovaný) inicializátor třídy UIGestureRecognizer. Jeho prostřednictvím nejen vytvoříme požadovanou instanci, ale také specifikujeme objekt, který má být informován o tom, že uživatel provedl odpovídající gesto – obvykle půjde o řídicí objekt rámce –, a zprávu, již recognizer tomuto objektu pošle.
V závislosti na tom, o jaké gesto se jedná, je možné, že zprávu objekt dostane pouze jednou (např. při klepnutí), nebo že ji dostane v průběhu gesta pokaždé, když se jeho atributy změní (např. při tažení).
-(void)addGestureRecognizer:(UIGestureRecognizer*)gr;
Druhou z metod nenalezneme ve třídě UIGestureRecognizer, ale v samotném rámci – tedy ve třídě UIView; nedělá nic jiného, než že k rámci recognizer připojí. Knihovní kód se pak již automaticky postará o to, aby všechny připojené recognizery měly možnost zpracovat události, spojené s gesty nad daným rámcem (v podstatě nejde o nic jiného, než že okno přesměruje zprávy touches...withEvent: recognizerům, jež jsou s rámcem spojeny).
Konkrétní příklady
Ukažme si pro lepší ilustraci několik příkladů; pro jednoduchost budeme předpokládat, že níže uvedený kód je vždy součástí řídicího objektu rámce (tedy vhodného dědice třídy UIViewController).
Prvý z příkladů už nemůže být jednodušší – zajistí, že po klepnutí do rámce bude vždy zavolána jeho metoda tapped:
-(void)viewDidLoad {
...
UIGestureRecognizer *tgr=[[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(tapped)];
[self.view addGestureRecognizer:tgr];
[tgr release];
...
}
-(void)tapped {
...
}
Druhý příklad ukazuje i jednoduché konkrétní nastavení; opět jako příklad použijeme standardní třídu UITapGestureRecognizer (kompletní seznam standardních recognizerů a možností, které nám nabízejí, si ukážeme později):
-(void)viewDidLoad {
...
UITapGestureRecognizer *dtgr=[[UITapGestureRecognizer alloc]
initWithTarget:self
action:@selector(tappedTwiceWithRecognizer:)];
[self.view addGestureRecognizer:dtgr];
dtgr.numberOfTapsRequired=2;
[dtgr release];
...
}
-(void)tappedTwiceWithRecognizer:(UITapGestureRecognizer*)dtgr {
...
}
Povšimněme si, že tentokrát bylo zapotřebí deklarovat proměnnou, obsahující odkaz na recognizer, jako instanci konkrétní třídy UITapGestureRecognizer – to proto, abychom měli k dispozici její atribut numberOfTapsRequired. Také zde vidíme, že akce může (ale nemusí, jak ukázal prvý příklad) mít jeden argument; je-li tomu tak, je jím právě recognizer, který ji vyvolal.
Další služby
Samozřejmě, že k jednomu rámci můžeme připojit libovolně mnoho recognizerů – kupříkladu oba dva z výše uvedených příkladů. Pak ovšem narazíme na problém, který jsme poznali už dříve, když jsme klepnutí a vícenásobné klepnutí interpretovali přímo: pokud bychom chtěli, aby dvojí klepnutí nebylo nejprve interpretováno jako jednoduché (tedy abychom v našem konkrétním případě nedostali zprávu tapped vždy před zprávou tappedTwiceWithRecognizer:), je třeba se o to postarat speciálním způsobem.
Recognizery samy nabízejí službu, která umožní takovéto závislosti deklarovat: je jí zpráva requireGestureRecognizerToFail:, kterou si vyžádáme, aby jeden recognizer "fungoval" pouze v případě, že jiný gesto nerozpozná. Můžeme tedy napsat např. takovýto kód:
-(void)viewDidLoad {
...
UIGestureRecognizer *tgr=[[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(tapped)];
[self.view addGestureRecognizer:tgr];
[tgr release];
UITapGestureRecognizer *dtgr=[[UITapGestureRecognizer alloc]
initWithTarget:self
action:@selector(tappedTwiceWithRecognizer:)];
[self.view addGestureRecognizer:dtgr];
dtgr.numberOfTapsRequired=2;
[dtgr release];
[tgr requireGestureRecognizerToFail:dtgr]; // *
...
}
Pomocí řádku označeného hvězdičkou zajistíme, že recognizer tgr (který reaguje na jednoduché klepnutí a dojde-li k němu, pošle zprávu tapped) neudělá nic, dokud recognizer dtgr (který reaguje na dvojí klepnutí) nezjistí, že gesto neodpovídá. Jinými slovy – dvojí klepnutí pošle zprávu tappedTwiceWithRecognizer:, ale nikoli zprávu tapped.
Samozřejmě, že – přesně stejně, jako když jsme interpretovali gesta přímo – před posláním zprávy tapped uplyne nějaká chvilka, v níž musí systém počkat, zda druhé klepnutí nastane nebo ne. Tomu se nelze nijak vyhnout.
Přístup k recognizeru uvnitř posílané zprávy umožňuje zjistit pozici uvnitř rámce, na níž gesto nastalo (nebo na níž právě probíhá u složitějších gest):
-(void)tappedTwiceWithRecognizer:(UITapGestureRecognizer*)dtgr {
NSLog(@"Klepnuto na pozici %@",NSStringFromCGPoint(
[dtgr locationInView:self.view]
)];
}
Recognizery toho nabízejí ještě více: můžeme např. pomocí zprávy addTarget:action: deklarovat více různých příjemců více různých zpráv při rozpoznání gesta, nebo můžeme využít atributu delegate spolu s objektem, odpovídajícím protokolu UIGestureRecognizerDelegate, pro detailní sledování běhu recognizeru a také pro řízení jeho aktivity a souběhu s oststními recognizery, ještě jemnější a flexibilnější, než prostá deklarace requireGestureRecognizerToFail:, popsaná výše. To je ale v praxi zapotřebí poměrně výjimečně, takže detailně si to popisovat nebudeme.
Namísto toho se příště podíváme na seznam konkrétních hotových recognizerů, jež nám iOS nabízí.
Obsah seriálu (více o seriálu):
- Nastal čas na kakao...
- Tak nejdřív kakao ochutnáme...
- Programovací jazyk C: velmi, velmi stručně
- Objective C: to si vysvětlíme podrobněji
- Co jsme si o Objective C ještě neřekli...
- Nastal čas na kakao - Vznik a zánik objektů
- Nastal čas na kakao - Kopírování objektů
- Nastal čas na kakao - Skryté podtřídy
- Nastal čas na kakao - Základní služby objektů
- Nastal čas na kakao - Jak správně psát v Objective C
- Nastal čas na kakao - Jak správně importovat
- Nastal čas na kakao - Podtřídy, delegáti, vkládání, jak se to rýmuje?
- Nastal čas na kakao - Využití kategorií namísto dědičnosti
- Nastal čas na kakao - Vkládání objektů a přesměrování zpráv
- Nastal čas na kakao - Inicializace a rušení objektů
- Nastal čas na kakao - Metody initWith... a designovaný inicializátor
- Nastal čas na kakao - Inicializace: tipy a triky
- Nastal čas na kakao - Accesory: přístup k proměnným instancí
- Nastal čas na kakao - Šedá je teorie, zelený je strom života...
- Nastal čas na kakao - Více o XCode: inspektory
- Nastal čas na kakao - Aplikace RSS2: datový model
- Nastal čas na kakao - Aplikace RSS: implementace datového modelu
- Nastal čas na kakao - Aplikace RSS: parsování XML
- Nastal čas na kakao - Interface Builder a uživatelské rozhraní
- Nastal čas na kakao - Interface Builder: atributy objektů
- Nastal čas na kakao - Interface Builder: atributy objektů
- Nastal čas na kakao - Druhý kontrolér a dokončení aplikace
- Nastal čas na kakao - Drobná vylepšení a zdokonalení...
- Nastal čas na kakao - Ladění
- Nastal čas na kakao - Třídy Foundation Kitu
- Nastal čas na kakao - Třídy Foundation Kitu (2)
- Nastal čas na kakao - Textové řetězce: NS(Mutable)String
- Nastal čas na kakao - Čísla, binární data a další...
- Nastal čas na kakao - Archivace objektů
- Nastal čas na kakao - Trocha magie, aneb distribuované objekty
- Nastal čas na kakao - Málem bychom zapomněli: NSAutoreleasePool
- Nastal čas na kakao - Zpracování výjimek: NSException
- Nastal čas na kakao - NSInvocation a černá magie
- Nastal čas na kakao - Kakao v Tygrovi
- Nastal čas na kakao - Notifikace: nepřímé předávání zpráv
- Nastal čas na kakao - NSUserDefaults
- Nastal čas na kakao - Co nového ve Foundation Kitu
- Nastal čas na kakao – s Intelem, s Intelem, jedeme do...
- Co nového v Xcode
- Začínáme s AppKitem
- Jak MVC v Kakau vypadá doopravdy?
- Jak MVC v Kakau vypadá doopravdy: dokončení
- Přehled tříd AppKitu
- Nastal čas na kakao - Přehled tříd AppKitu 2
- Přehled tříd AppKitu 3: zbývající třídy GUI
- Přehled tříd AppKitu 4: textový systém
- Nastal čas na kakao - Přehled tříd AppKitu 5: hlavně grafika
- Přehled tříd AppKitu 6: dokumentový systém
- Přehled tříd AppKitu 7: dokončení
- Pojmenované vlastnosti objektů
- Pojmenované vlastnosti objektů: implementace
- Pojmenované vlastnosti objektů: relace 1:N
- Pojmenované vlastnosti objektů: řazení jmen a agregační funkce
- Sledování změn objektů
- Sledování změn objektů – ukázka
- Sledování změn objektů – zdrojový kód
- Sledování změn objektů: kód modelu
- Sledování změn objektů: přímý přístup
- Kontroléry a vazby
- Vázání vazeb
- Další vazby s jednoduchým kontrolérem
- Implementace a použití převodu hodnot
- Validace hodnot
- Validace a chyby, a jedna hezká vazba...
- Práce s polem objektů
- Základní vazby NSArrayControlleru
- Převodníky, přepínače, placeholdery
- Mírná vylepšení v mezích zákona
- Objective C 2.0 - novinky z Leoparda
- NSTreeController
- Programování v Cocoa - Pár tipů a triků
- Programování v Cocoa - Základy kreslení
- Kterak nakreslit modrý obdélník...
- Další služby pro kreslení
- Obrázky a písmenka...
- Události a myš
- Lepší práce s myší
- Události klávesnice
- Input Management
- Příkazy a schránka
- Další události
- Táhni a padni
- Byli jsme na tahu; nyní padneme.
- Zvolme si, jak vhodit
- Drobnosti a chybičky
- Speciální případy tahání či házení
- Kterak táhnout něco, co neexistuje?
- Jak na sítě...
- NSURLConnection
- Safari za minutu
- Služby WebKitu
- Kakao v Leopardu
- Druhé Objective C
- Druhé Objective C: různé drobnosti
- Druhé Objective C: kategorie a protokoly
- Druhé Objective C: nový příkaz cyklu
- Druhé Objective C: atributy a accesory
- Druhé Objective C: atributy a accesory
- 64 je dvakrát 32
- Ubicumque dulce est, ibi et acidum invenies...
- Irbis: že prý žádné novinky?
- Blok sem, blok tam, nám už je to všechno jasné...
- Bloky jsou i v AppKitu
- Irbis a Foundation Kit
- Kde jsou má data?
- Kde jsou má data? V NSCache!
- Soubor, jméno, URL, jak se to rýmuje...
- Další podpora NSURL
- Zabíjení!
- A máme tady i...OS!
- Systémové prvky GUI
- Programování pro iOS 1. díl - Rozdíly mezi "i" a "Mac"
- Programování pro iOS - 2. Začínáme programovat
- Programování pro iOS - 3. základní ovladače a propojení GUI s kódem
- Programování pro iOS - 4. Varovná hlášení
- Programování pro iOS - 5. Rámce a jejich řídicí objekty
- Programování pro iOS - 6. Ukládání dat
- Programování pro iOS - 7. Správa paměti a starý restík
- Programování pro iOS - 8. Dokončení aplikace
- Programování pro iOS - 9. Jak dostat aplikaci do iPhone
- Programování pro iOS - 10. Instalace aplikace do cizího iPhone
- Programování pro iOS - 11. Jak dostat aplikaci do libovolného iPhone
- Programování pro iOS - 12. Touching!
- Programování pro iOS - 13. Kreslíme na iPhone
- Programování pro iOS - 14. Udělejme gesto
- Programování pro iOS - 15. Další gesta
- Programování pro iOS - 16. Více prstů, více zábavy
- Programování pro iOS - 17. Podpora standardních gest
- Programování pro iOS - 18. Recognizery v iOS
- Programování pro iOS - 19. Další standardní recognizery
- Programování pro iOS - 20. Co nového v iOSu
- Programování pro iOS - 21. "Multitasking"
- Programování pro iOS - 22. Nulla est honesta avaritia nisi temporis
- Programování pro iOS - 23. Jak se aktivovat, jsme-li v pozadí
- Programování pro iOS - 24. Zbývající drobnosti
- Programování pro iOS - 25. Řídicí objekty rámců
- Programování pro iOS - 26. Jak se dělá UIViewController
- Programování pro iOS - 27. Kde vzít rámce
- Programování pro iOS - 28. Základní služby
- Programování pro iOS - 29. Práce s rámci
- Programování pro iOS - 30. Rotace zařízení
- Programování pro iOS - 31. Správa paměti v rámcích
- Programování pro iOS - 32. Řídicí objekt pro tabulky
- Programování pro iOS - 33. Řídicí objekt pro strom
- Programování pro iOS - 33. Více o UINavigationControlleru
- Programování pro iOS - 35. Ještě jednou UINavigationController
- Programování pro iOS - 36. Po navigátoru taby
- Programování pro iOS - 37. Více o UITabBarControlleru
- Programování pro iOS - 38. Dokončení UITabBarControlleru
- Programování pro iOS - 39. UIPopoverController
- Programování pro iOS - 40. Další triky UIPopoverControlleru
- Programování pro iOS - 41. Zbývající služby UIPopoverControlleru
- Programování pro iOS - 42. UISplitViewController
- Programujeme v
iTunesXcode 4 - Programování pro iOS - 44. Předvolby Xcode 4
- Programování pro iOS - 45. Práce v Xcode 4
- Xcode 4: projekt a cíle
- Xcode 4: práce s cíli
- Xcode 4: Build Settings
- Xcode 4: Build Phases
- Xcode4: Build Phases podruhé
- Xcode 4: Co jsou to Build Rules?
- Xcode4: taje editoru
- Xcode4: automatické doplňování v editoru
- XIBy chyby
- Více o XIBech
- Editor XIBů
- Inspektory pro XIBy
- Vazby mezi objekty v XIBech
- Vazby mezi objekty v kódu
- Paletky Xcode pro XIBy
- Xcode 4: levý sloupec
- Xcode 4: okno Organizer
- Xcode 4: okno Organizer, část druhá
- Xcode 4: co je to Workspace?
- Xcode 4: základy schémat
- Xcode 4: akční schémata