Programování pro iOS - 18. Recognizery v iOS - 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 - 18. Recognizery v iOS

1. prosince 2010, 00.00 | Další díl našeho seriálu o programování zařízení s iOS se zabývá konkrétními recognizery, které v systému naleznete. Zde jsou prvé z nich.

V několika dílech jsme si ukázali standardní podporu metod touches...withEvent: na úrovni rámců a dalších objektů ve frontě responderů – tedy především řídicích objektů rámců (typicky instancí nějaké podtřídy UIViewController). Minule pak jsme se seznámili s třídou UIGestureRecongnizer a s jejími službami, jež umožňují obecnou implementaci rozpoznání gesta. Ke konkrétnímu rámci, v němž chceme gesto rozpoznávat, pak recognizer jen připojíme pomocí standardního API, a standardní knihovny (především kód třídy UIWindow) se pak postarají o ostatní.

UITapGestureRecognizer

Základní recognizer, který rozeznává různá klepnutí; ukázali jsme si jej už v příkladech v minulém dílu. Akci posílá ve chvíli, kdy k požadovanému typu klepnutí došlo.

Pro specifikaci požadovaného typu klepnutí nabízí dvojici atributů:

numberOfTapsRequired – počet klepnutí;

numberOfTouchesRequired – počet prstů, jimiž se klepe.

U klepnutí více prsty jeho metoda locationInView: vrací bod uprostřed. Pro vícenásobná klepnutí se bere v úvahu poloha toho prvého z nich.

Standardní hodnotou obou atributů je logicky 1.

UILongPressGestureRecognizer

Druhý z recognizerů rozeznává "stisknutí", pro jehož základní implementaci nad primitivními službami pro zpracování gest, jak jsme viděli, by byl zapotřebí časovač.

Nabízí ne méně než čtyři atributy; typicky však budeme využívat jen dva z nich, stejné jako u třídy UITapGestureRecognizer:

numberOfTapsRequired – počet klepnutí;

numberOfTouchesRequired – počet prstů, jimiž se klepe.

a také s výchozí hodnotou 1. Zbývající dva atributy umožňují změnit standardní chování gesta, což v běžných případech není vhodné – až na výjimky by totéž gesto samozřejmě mělo být i v různých aplikacích interpretováno stejně:

minimumPressDuration – doba stisknutí v sekundách, standardně 0.4;

allowableMovement – maximální povolený posun prstu, standardně 10 pixelů. Změní-li se poloha o více, již se to nepovažuje za stisknutí.

Recognizer UILongPressGestureRecognizer posílá svou akci vícekrát: nejprve po uplynutí minimumPressDuration, pak po každé změně polohy prstu – takže je snadno možné implementovat kombinovaná gesta typu stisknout-a-táhnout – a nakonec ve chvíli, kdy gesto končí (prst je zvednut). Chceme-li tyto případy rozlišit, můžeme využít tzv. stav recognizeru – jde o atribut state, jehož hodnoty mohou být následující:

UIGestureRecognizerStatePossible – zatím nic nevíme, akce v tomto stavu posílána není;

UIGestureRecognizerStateBegan – gesto bylo právě rozpoznáno, akce je poslána poprvé;

UIGestureRecognizerStateChanged – změnil se stav gesta, v případě třídy UILongPressGestureRecognizer tedy poloha prstu;

UIGestureRecognizerStateEnded – gesto bylo ukončeno, akce je poslána naposled;

UIGestureRecognizerStateCancelled – gesto bylo přerušeno (UILongPressGestureRecognizer tohoto stavu nenabývá);

UIGestureRecognizerStateFailed – gesto nebylo rozeznáno, akce v tomto stavu posílána není;

UIGestureRecognizerStateRecognized – gesto bylo rozpoznáno (UILongPressGestureRecognizer v tomto stavu samostatnou akci neposílá, byla by duplicitní s UIGestureRecognizerStateBegan).

Zajímá-li nás tedy – jak bývá poměrně obvyklé – pouze stisknutí (ale ne změny polohy ani zvednutí prstů), můžeme použít např. následující implementace:

-(void)viewDidLoad {
  ...
  UILongPressGestureRecognizer *lgr=     [[UILongPressGestureRecognizer alloc]
      initWithTarget:self action:@selector(pressed:)];
  [self.view addGestureRecognizer:lgr];
  [lgr release];
  ...
}
-(void)pressed:(UILongPressGestureRecognizer*)lgr {
  if (lgr.state!=UIGestureRecognizerStateBegan) return;
  ...
}

UIPanGestureRecognizer

Gesto "pan" je to, čemu jsme říkali "drag" či "move" – prostě posun prstu po obrazovce.

Pro detailní specifikaci máme k dispozici jen dva atributy; ty určují minimální a maximální počet prstů, jejichž tažení nás zajímá:

minimumNumberOfTouches – je-li počet prstů, jimiž se klepe, menší než toto číslo, gesto se nerozpozná. Standardní hodnota je 1;

maximumNumberOfTouches – je-li počet prstů, jimiž se klepe, vyšší než toto číslo, gesto se nerozpozná. Standardní hodnota je "hodně" (NSUIntegerMax).

V praxi tam, kde nás zajímá jen tažení jedním prstem, často necháváme atribut maximumNumberOfTouches beze změny, a zároveň necháme atribut multipleTouchEnabled rámce nastaven na NO.

Je samozřejmé, že recognizer UIPanGestureRecognizer funguje podobně jako UILongPressGestureRecognizer: akci posílá vícekrát, poprvé hned po rozeznání gesta se stavem UIGestureRecognizerStateBegan, pak po každé změně polohy prstu se stavem UIGestureRecognizerStateChanged, a nakonec po zvednutí prstu se stavem UIGestureRecognizerStateEnded.

Pro větší programátorské pohodlí nabízí UIPanGestureRecognizer vedle standardní služby locationInView: (jež samozřejmě vždy informuje o aktuální poloze taženého prstu) také dvojici metod

-(CGPoint)velocityInView:(UIView*)view;

Rychlost posunu.

-(CGPoint)translationInView:(UIView*)view;

Posunutí v průběhu gesta – pokud chceme tažením měnit polohu nějakého objektu, je tato informace právě to, co nás zajímá.

Měníme-li polohu objektu průběžně, je samozřejmě po změně třeba posun v rámci recognizeru vynulovat, abychom příště dostali zase jen "novou" změnu, a nikoli změnu od začátku gesta; k tomu slouží třetí metoda:

-(void)setTranslation:(CGPoint)translation inView:(UIView*)view;

Typická implementace tedy vypadá zhruba nějak takto:

-(void)viewDidLoad {
  ...
  UIPanGestureRecognizer *dgr=[[UIPanGestureRecognizer alloc]
    initWithTarget:self action:@selector(dragged:)];
  [self.view addGestureRecognizer:dgr];
  [dgr release];
  ...
}
-(void)dragged:(UIPanGestureRecognizer*)dgr {
  if (dgr.state==UIGestureRecognizerStateBegan) {
    ... příprava tažení ...
  } else if (dgr.state==UIGestureRecognizerStateChanged) {
    CGPoint dragBy=[dgr translationInView:self.view];
    ... posun o dragBy ...
    [dgr setTranslation:CGPointZero inView:self.view];
  }
}

Příště se podíváme na zbývající standardní recognizery.

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  

Poslat článek

Nyní máte možnost poslat odkaz článku svým přátelům:

Váš e-mail:

(Není povinný)

E-mail adresáta:

Odkaz článku:

Vzkaz:

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: