Componentele animate cu Dynamics UIKit Partea 2

Introducere

În primul tutorial al acestei serii scurte despre UIKit Dynamics, am învățat elementele de bază ale API prin crearea unei componente de meniu animate. În acest tutorial, vom continua să lucrăm la proiectul nostru și vom implementa o altă componentă animată, o vizualizare personalizată de alertă.

1. Prezentare generală

Vizualizarea implicită de alertă pe iOS este excelentă, dar nu este foarte personalizabilă în ceea ce privește aspectul și comportamentul. Dacă aveți nevoie de o vizualizare de alertă care să fie personalizabilă, atunci trebuie să vă creați propria soluție și asta vom face în acest tutorial. Acest tutorial se axează pe comportamentul vizualizării de alertă și nu pe funcționalitatea acesteia. Să vedem care este rezultatul pe care îl urmăm

Vizualizarea de alertă va fi a UIView exemplu la care vom adăuga următoarele sub-viziuni:

  • UILabel obiect pentru afișarea titlului vizualizării avertizării
  • UILabel obiect pentru afișarea mesajului vizualizării avertizării
  • una sau mai multe UIButton instanțe pentru a permite utilizatorului să interacționeze cu vizualizarea de alertă

Vom folosi UISnapBehavior clasa pentru a prezenta vizualizarea alertei. După cum indică și numele, aceasta UIDynamicBehavior subclasa forțează un element dinamic să se apropie de un punct ca și cum ar fi fost atras de el magnetic.

UISnapBehavior clasa definește o proprietate suplimentară, amortizare, care definește cantitatea de oscilație atunci când elementul dinamic a atins punctul în care este atras.

Vom folosi un comportament gravitațional, în combinație cu un comportament de coliziune și împingere, pentru a respinge viziunea de alertă. Amintiți-vă că am folosit deja aceste comportamente în tutorialul anterior.

Vizualizarea de alertă va fi animată din partea de sus a ecranului. Când vizualizarea alertă este pe cale să apară, comportamentul instantaneu o va face să cadă în vedere și să se fixeze în centrul ecranului. Pentru a elimina vizualizarea de alertă, un comportament de împingere îl va împinge pe scurt în partea de jos a ecranului și un comportament gravitator îl va trage apoi în partea de sus a ecranului și îl va face animat off-screen.

Vom crea o metodă de inițializare personalizată pentru componenta de vizualizare a alertelor care acceptă titlul, mesajul, titlurile butoanelor și vizualizarea părintelui. Nu vom implementa un protocol delegat pentru vizualizarea de alertă. În schimb, vom face uz de blocuri, ceea ce înseamnă o soluție mai elegantă și mai modernă. Blocul sau manipulatorul vor accepta doi parametri, indicele și titlul butonului pe care utilizatorul l-a lovit.

De asemenea, vom afișa o vedere semi-transparentă în spatele vizualizării de avertizare, pentru a împiedica interacțiunea cu viziunea părinte a acestuia, atâta timp cât vizualizarea de alertă este vizibilă. Să începem să aruncăm o privire asupra proprietăților vizualizării alertei și a inițializatorului personalizat.

2. Proprietăți și inițializare

Pasul 1: Crearea clasei de vizualizare a alertelor

presa Command-N pe tastatură pentru a crea un fișier nou și pentru a selecta Clasa obiectiv-C din lista de iOS template-uri. Faceți-i o subclasă de NSObject și numește-o AlertComponent.

Pasul 2: Declararea proprietăților

Următorul pas este să declarăm câteva proprietăți private. Deschis AlertComponent.m, adăugați o extensie de clasă în partea de sus și declarați următoarele proprietăți:

@interface AlertComponent () @property (nonatomic, puternic) UIView * alertView; @property (nonatomic, puternic) UIView * backgroundView; @property (nonatomic, puternic) UIView * targetView; @property (nonatomic, puternic) UILabel * titleLabel; @property (nonatomic, puternic) UILabel * messageLabel; @property (nonatomic, puternic) UIDynamicAnimator * animator; @property (nonatomic, strong) NSString * title; @property (nonatomic, strong) NSString * message; @property (nonatomic, puternic) NSArray * buttonTitles; @property (nonatomic) CGRect initialAlertViewFrame; @Sfârșit

Funcția fiecărei proprietăți va deveni clară pe măsură ce implementăm componenta de alertă. Este timpul să creați inițializatorul personalizat al componentei.

Pasul 3: Inițializare

Așa cum am menționat deja, vom folosi un inițializator personalizat pentru a face lucrul cu componenta de alertă cât mai ușor posibil. Initializatorul acceptă patru parametri, titlul alertului, mesajul, titlurile butoanelor și vizualizarea la care va fi adăugată componenta de alertă, vizualizarea părinte. Deschis AlertComponent.h și adăugați următoarea declarație:

@interface AlertComponent: NSObject - (id) initAlertWithTitle: (NSString *) titlul și mesaj: (NSString *) mesaj șiButtonTitles: (NSArray *) butonTitle șiTargetView: (UIView *) targetView; @Sfârșit

3. Configurarea Vizualizării Avertizării

Pasul 1: Declarația metodelor de instalare

În această parte, va fi creată vizualizarea de alertă și vor fi adăugate toate subdiviziuni. De asemenea, vor fi configurate vizualizarea de fundal, precum și animatorul dinamic.

Deschis AlertComponent.m și declarați următoarele metode private în extensia de clasă privată:

@interface AlertComponent () ... - (void) setupBackgroundView; - (void) setupAlertView; @Sfârșit

Numele de metode sunt explicite. Să începem prin implementarea setupAlertView mai întâi, deoarece cea mai mare parte a configurației alertei are loc în această metodă.

Pasul 2: Configurarea Vizualizării de avertizare

În setupAlertView, facem trei lucruri:

  • inițializați și configurați vizualizarea de alertă
  • inițializați și configurați etichetele afișării avertizărilor
  • inițializați și configurați butoanele vizualizării de alertă

Să începem prin calcularea dimensiunii și poziției ecranului de alertă așa cum se arată în fragmentul de cod de mai jos.

- (void) setupAlertView // Setați dimensiunea ecranului de alertă. CGSize alertViewSize = CGSizeMake (250.0, 130.0 + 50.0 * auto.buttonTitles.count); // Stabiliți punctul de origine inițial în funcție de direcția vizualizării alertei. CGPoint inițialOriginPoint = CGPointMake (auto.targetView.center.x, self.targetView.frame.origin.y - alertViewSize.height); 

Începem setând dimensiunea ecranului de alertă. Pentru a face dinamica vederii dinamice, adaugam 50.0 indică înălțimea sa pentru fiecare buton. De asemenea, rețineți că originea inițială a vizualizării de alertă este off-screen. Următorul pas este inițializarea și configurarea vizualizării de alertă:

auto.alertView = [[UIView alocare] initWithFrame: CGRectMake (initialOriginPoint.x, initialOriginPoint.y, alertViewSize.width, alertViewSize.height)]; // Culoare de fundal. [auto.alertView setBackgroundColor: [culoare UICcolorWithRed: 0.94 verde: 0.94 albastru: 0.94 alfa: 1.0]]; // Faceți vizualizarea alertă cu colțuri rotunjite. [auto.alertView.layer setCornerRadius: 10.0]; // Stabiliți o margine în ecranul de alertă. [auto.alertView.layer setBorderWidth: 1.0]; [auto.alertView.layer setBorderColor: [UICcolor negruColor] .CGColor]; // Atribuiți cadrul de vizualizare inițială cu proprietatea respectivă. self.initialAlertViewFrame = auto.alertView.frame; 

Utilizarea alertViewSize și initialOriginPoint, inițializăm alertView obiect și setați culoarea de fundal. Închidem colțurile ecranului de alertă prin setarea lui strat„s cornerRadius la 10.0, este lățimea graniței la 1.0, si este borderColor La negru. De asemenea, stocăm cadrul inițial al vizualizării de alertă initialAlertViewFrame deoarece noi vom avea nevoie mai târziu.

Dacă Xcode vă spune că nu știe despre alertView„s strat proprietate, apoi adăugați următoarea declarație de import în partea de sus a fișierului de implementare:

#import  

Este timpul să adăugați etichetele. Să începem cu eticheta titlului.

// Configurați eticheta titlului. auto.titleLabel = [[UILabel alocare] initWithFrame: CGRectMake (0.0, 10.0, self.alertView.frame.size.width, 40.0)]; [auto.titleLabel setText: auto.titul]; [auto.titleLabel setTextAlignment: NSTextAlignmentCenter]; [auto.titleLabel setFont: [UIFont fontWithName: @ "Avenir-Heavy" dimensiune: 14.0]]; // Adăugați eticheta de titlu în ecranul de alertă. [self.alertView addSubview: self.titleLabel];

Setarea etichetei mesajului este destul de similară.

// Configurați eticheta mesajului. auto.messageLabel = [[UILabel alocare] initWithFrame: CGRectMake (0.0, auto.titleLabel.frame.origin.y + auto.titleLabel.frame.size.height, self.alertView.frame.size.width, 80.0)]; [auto.messageLabel setText: self.message]; [auto.messageLabel setTextAlignment: NSTextAlignmentCenter]; [self.messageLabel setFont: [UIFont fontWithName: @ "Avenir" dimensiune: 14.0]]; [auto.messageLabel setNumberOfLines: 3]; [auto.messageLabel setLineBreakMode: NSLineBreakByWordWrapping]; // Adăugați eticheta mesajului în ecranul de alertă. [self.alertView addSubview: self.messageLabel];

Rețineți că numberOfLines proprietatea este setată la 3 și lineBreakMode este setat sa NSLineBreakByWordWrapping.

Ultimul lucru pe care trebuie să-l configurați sunt butoanele vizualizării alertului. Chiar dacă numărul de butoane poate varia, configurarea și poziționarea butoanelor este destul de simplă. Separăm butoanele de 5 puncte și folosiți a pentru pentru a le inițializa.

CGFloat lastSubviewBottomY = auto.messageLabel.frame.origin.y + auto.messageLabel.frame.size.height; pentru (int i = 0; i<[self.buttonTitles count]; i++)  UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(10.0, lastSubviewBottomY + 5.0, self.alertView.frame.size.width - 20.0, 40.0)]; [button setTitle:[self.buttonTitles objectAtIndex:i] forState:UIControlStateNormal]; [button.titleLabel setFont:[UIFont fontWithName:@"Avenir" size:13.0]]; [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [button setTitleColor:[UIColor yellowColor] forState:UIControlStateHighlighted]; [button setBackgroundColor:[UIColor colorWithRed:0.0 green:0.47 blue:0.39 alpha:1.0]]; [button addTarget:self action:@selector(handleButtonTap:) forControlEvents:UIControlEventTouchUpInside]; [button setTag:i + 1]; [self.alertView addSubview:button]; lastSubviewBottomY = button.frame.origin.y + button.frame.size.height; 

Rețineți că fiecare buton invocă handleButtonTap: atunci când este utilizată. Putem determina ce buton a fost utilizat de utilizator prin inspectarea butoanelor etichetă proprietate.

În cele din urmă, adăugați vizualizarea de alertă la vizualizarea țintă sau părinte adăugând următoarea linie în partea de jos a metodei setupAlertView:

// Adăugați vizualizarea de alertă la vizualizarea părinte. [self.targetView addSubview: self.alertView];

Pasul 3: Configurarea vederii de fundal

A doua metodă pe care trebuie să o implementăm este setupBackgroundView. Vederea de fundal va împiedica utilizatorul să interacționeze cu vizualizarea parentală a vizualizării de avertizare atât timp cât este afișată vizualizarea de alertă. Am stabilit-o inițial alfa proprietate la 0.0, ceea ce înseamnă că este transparent.

- (void) setupBackgroundView auto.backgroundView = [[UIView alocare] initWithFrame: self.targetView.frame]; [auto.backgroundView setBackgroundColor: [UICcolor griColor]]; [auto.backgroundView setAlpha: 0.0]; [self.targetView addSubview: auto.backgroundView]; 

Pasul 4: Implementarea inițializatorului

Cu setupAlertView și setupBackgroundView gata de utilizare, să implementăm inițializatorul personalizat pe care l-am declarat anterior.

- (id) * initAlertWithTitle: (NSString *) mesajul title șiMessage: (NSString *) șiButtonTitles: (NSArray *) butonulTitle șiTargetView: (UIView *) targetView if (self = [super init] proprietăți. auto.title = titlu; self.message = mesaj; self.targetView = targetView; auto.buttonTitles = butoane; // Configurați vizualizarea de fundal. [auto setupBackgroundView]; // Configurați vizualizarea avertizării. [self setupAlertView]; // Configurați animatorul. self.animator = [[Alocare UID dynamicAnimator] initWithReferenceView: self.targetView];  întoarce-te; 

Am setat titlu, mesaj, targetView, și buttonTitles proprietăți, invoca setupBackgroundView și setupAlertView, și inițializează animatorul dinamic, trecând self.targetView ca vedere de referință.

4. Afișare vizualizare avertizare

Pentru a afișa vizualizarea alertei după ce a fost inițializată, trebuie să declarăm și să implementăm o metodă publică care poate fi apelată, de exemplu, de către controlerul de vizualizare care găzduiește vizualizarea de avertizare. Deschis AlertComponent.h și adăugați următoarea declarație de metodă:

- showAlertView (void);

Înapoi la AlertComponent.m a implementa showAlertView. Așa cum am menționat mai devreme în acest tutorial, vom folosi un nou UIDynamicBehavior subclasa pentru a afișa vizualizarea de alertă, UISnapBehavior. Să vedem cum folosim această clasă showAlertView.

- (void) showAlertView [self.animator removeAllBehaviors]; UISnapBehavior * snapBehavior = [[UISnapBehavior aliniere] initWithItem: self.alertView snapToPoint: self.targetView.center]; snapBehavior.damping = 0.8; [self.animator addBehavior: snapBehavior]; [UIView animateWithDuration: 0.75 animații: ^ [auto.backgroundView setAlpha: 0.5]; ]; 

Începem prin eliminarea oricăror comportamente dinamice existente de la animatorul dinamic pentru a ne asigura că nu apar conflicte. Amintiți-vă că unele comportamente dinamice pot fi adăugate o singură dată animatorului dinamic, cum ar fi un comportament gravitațional. De asemenea, vom adăuga și alte comportamente dinamice pentru a respinge vizualizarea de alertă.

După cum puteți vedea, folosirea unui comportament rapid nu este dificilă. Specificăm elementul dinamic al cărui comportament trebuie aplicat și setăm punctul la care ar trebui să se fixeze elementul dinamic. De asemenea, setăm comportamentul amortizare proprietate așa cum am discutat mai devreme. De asemenea, rețineți că animăm alfa proprietatea vederii de fundal.

Pentru a testa vizualizarea de alertă, trebuie să efectuăm câteva modificări la ViewController clasă. Să începem prin adăugarea a UIButton exemplu la vizualizarea controlerului de vizualizare pentru a afișa vizualizarea de avertizare. Deschis Main.storyboard și trageți a UIButton exemplu de la Biblioteca de obiecte la vizualizarea controlerului de vizualizare. Poziționați butonul în partea de jos a ecranului și dați-i un titlu Afișați Vizualizare avertizare. Adăugați o acțiune la ViewController.h așa cum se arată mai jos.

@ interfață ViewController: UIViewController - (IBAction) showAlertView: (id) expeditor; @Sfârșit

Întoarceți-vă la storyboard și conectați acțiunea controlerului de vedere la buton. Deschis ViewController.m și importați fișierul antet al fișierului AlertComponent clasă.

#import "AlertComponent.h"

Apoi, declarați o proprietate în extensia de clasă privată de tip AlertComponent și numește-o alertComponent.

@ interfață ViewController () @property (nonatomic, puternic) MenuComponent * menuComponent; @property (nonatomic, strong) AlertComponent * alertComponent; - (void) showMenu: (UIGestureRecognizer *) gestureRecognizer; @Sfârșit

Apoi, inițializăm componenta de alertă în controlerul de vizualizare viewDidLoad metodă.

- (void) viewDidLoad ... // Initialize Alert Component auto.alertComponent = [[AlertComponent alloc] initAlertWithTitle: @ "Custom Alert" șiMessage: @ "Aveți un nou mesaj de poștă electronică, dar nu știu de la cine." șiButtonTitles: @ [@ "Arată-mă", @ "Nu-mi pasă", @ "Pentru mine, într-adevăr?"] șiTargetView: self.view]; 

Pentru a afișa componenta de alertă, invoca showAlertView: în acțiunea pe care tocmai am creat-o, showAlertView:.

- (IBAction) showAlertView: (id) expeditor [auto.alertComponent showAlertView]; 

Rulați aplicația și atingeți butonul pentru a afișa vizualizarea de avertizare. Rezultatul ar trebui să pară similar celui de mai jos.

5. Ascunderea Vizualizării Alertelor

După cum am văzut mai devreme, handleButtonTap: metoda este invocată atunci când utilizatorul pune pe butonul vizualizarea de alertă. Vizualizarea de alertă ar trebui să se ascundă atunci când unul dintre butoane este apăsat. Să vedem cum funcționează acest lucru.

Revedeți AlertComponent.m și, în extensia de clasă privată, declară handleButtonTap: metodă.

@interface AlertComponent () ... - (void) handleButtonTap: (UIButton *) expeditor; @Sfârșit

În această metodă, creăm un număr de comportamente dinamice și le adăugăm în obiectul animator dinamic. Comportamentele dinamice de care avem nevoie sunt:

  • un comportament gravitațional care trage viziunea de alertă spre partea de sus a ecranului
  • un comportament de coliziune cu o limită de ecran care oprește vizionarea alertei
  • un comportament de împingere care oferă viziunii de alertă puțin noroi spre partea de jos a ecranului

După eliminarea comportamentelor existente din animatorul dinamic și inițializarea comportamentului de împingere, după cum se arată mai jos.

- (void) handleButtonTap: (UIButton *) expeditor // Elimina toate comportamentele de la animator. [self.animator removeAllBehaviors]; UIPushBehavior * pushBehavior = [[UIPushBehavior alloc] initWithItems: modul [auto.alertView]: UIPushBehaviorModeInstantaneous]; [pushBehavior setAngle: M_PI_2 magnitudine: 20,0]; [self.animator addBehavior: pushBehavior]; 

unghi proprietatea comportamentului de împingere definește direcția împingerii. Prin setarea unghiului la M_PI_2, forța comportamentului de împingere este îndreptată spre partea inferioară a ecranului.

Următorul pas este adăugarea comportamentului gravitațional. Vectorul la care trecem setGravityDirection va duce la o forță spre partea de sus a ecranului, tragând vederea în sus.

UIGravityBehavior * gravityBehavior = [[UIGravityBehavior alocare] initWithItems: @ [auto.alertView]]; [gravitateBehavior setGravityDirection: CGVectorMake (0.0, -1.0)]; [auto.animator addBehavior: gravityBehavior];

Ceea ce interesează despre comportamentul de coliziune este acela că definim o limită care este off-screen.

UICcolisionBehavior * collisionBehavior = [[AlocareBehavior UIC] initWithItems: @ [auto.alertView]]; [collisionBehavior addBoundaryWithIdentifier: @ "alertCollisionBoundary" dinPoint: CGPointMake (auto.initialAlertViewFrame.origin.x, self.initialAlertViewFrame.origin.y - 10.0) toPoint: CGPointMake (auto.initialAlertViewFrame.origin.x + self.initialAlertViewFrame.size.width, auto.initialAlertViewFrame.origin.y - 10.0)]; [self.animator addBehavior: collisionBehavior];

De asemenea, avem nevoie de un comportament dinamic pentru a stabili elasticitatea coliziunii. Rezultatul este că vizualizarea alertă va scădea puțin atunci când se ciocnește cu limita off-screen.

UIDynamicItemBehavior * itemBehavior = [[UID dynamicItemBehavior alocat] initWithItems: @ [auto.alertView]]; itemBehavior.elasticity = 0.4; [self.animator addBehavior: itemBehavior];

De asemenea, trebuie să facem din nou viziunea de fundal transparentă. Facem acest lucru setând vizualizarea fundalului alfa proprietate la 0.0 într-un bloc de animație.

[UIView animateWithDuration: 2.0 animații: ^ [auto.backgroundView setAlpha: 0.0]; ];

Rulați încă o dată aplicația pentru a vedea rezultatul.

6. Manipularea interacțiunii utilizatorilor

Chiar dacă vizualizarea alertă răspunde la interacțiunea cu utilizatorul, în prezent nu știm ce buton a fost utilizat de utilizator. Asta ne vom concentra în această secțiune.

Așa cum am făcut și cu componenta de meniu, vom folosi blocuri pentru a rezolva această problemă. Blocurile fac pentru o soluție elegantă și pot fi adesea mai ușor de folosit decât un protocol delegat.

Începem prin actualizarea publicului showAlertView metodă. Metoda trebuie să accepte un handler de completare pe care vizualizarea de alertă o invocă atunci când utilizatorul a atins unul dintre butoane. În AlertComponent.h, actualizați declarația showAlertView metoda de la:

- showAlertView (void);

la:

- (void) showAlertViewWithSelectionHandler: (void (^) (butonul NSIntegerIndex, NSString * buttonTitle)) handler;

Operatorul de finalizare acceptă doi parametri, indicele de tip NSInteger, și titlul, de tip NSString, a butonului care a fost utilizat de utilizator. Dacă vrem să invocăm modulul handler de finalizare atunci când utilizatorul pune la dispoziție un buton din vizualizarea de alertă, trebuie să păstrăm o referință la instrumentul de completare. Aceasta înseamnă că trebuie să declarăm o proprietate pentru agentul de completare. Facem asta în extensia de clasă privată din AlertComponent.m.

@interface AlertComponent () ... @property (nonatomic, strong) void (^ selectionHandler) (NSInteger, NSString *); ... @end

Inca inauntru AlertComponent.m, actualizați descrierea metodei așa cum am făcut-o în fișierul antet cu un moment în urmă și stocați manualul de completare în selectionHandler proprietate, pe care tocmai am declarat-o.

- (void) showAlertViewWithSelectionHandler: (void (^) (NSInteger, NSString *)) handler auto.selecțieHandler = manipulator; ...

Ultima piesă a puzzle-ului invocă instructorul de completare handleButtonTap:, trecând în eticheta și titlul butonului.

- (void) handleButtonTap: (UIButton *) expeditor // Apelați selectorul de selecție. auto.selecțieHandler (sender.tag, sender.titleLabel.text); ...

AlertComponent este completă. Este timpul să testați totul. Înapoi la ViewController.m și actualizați acțiunea showAlertView: după cum se arată mai jos. După cum puteți vedea, noi invocăm noul showAlertViewWithSelectionHandler: și trece într-un bloc, care va fi apelat atunci când un utilizator din ecranul de alertă este apăsat de utilizator.

- (IBAction) showAlertView: (id) expeditor [auto.alertComponent showAlertViewWithSelectionHandler: ^ (butonul NSIntegerIndex, NSString * buttonTitle) NSLog (@ "% ld,% @", butonul lungIndex, butonulTitle); ];  

Asta e. Rulați încă o dată aplicația și examinați consola Xcode pentru a vedea rezultatul activității noastre.

Concluzie

UIKit Dynamics a fost introdus pentru prima oară în iOS 7 și vă poate ajuta să creați rapid animații realiste. Această serie scurtă a ilustrat faptul că mobilizarea UIKit Dynamics în proiectele dvs. nu este dificilă și nu trebuie să fiți un expert în matematică sau fizică.

Rețineți că UIKit Dynamics este destinat în primul rând pentru utilizarea în aplicații bazate pe vizualizare. Dacă sunteți în căutarea unei soluții similare pentru jocuri, vă recomandăm să aruncați o privire la Sprite Kit-ul Apple, care vizează dezvoltarea jocurilor.

Cod