Geanimeerde componenten met UIKit Dynamics deel 2

Invoering

In de eerste tutorial van deze korte serie over UIKit Dynamics leerden we de basis van de API door een geanimeerde menu-component te maken. In deze zelfstudie blijven we aan ons project werken en implementeren we een andere geanimeerde component, een aangepaste waarschuwingsweergave.

1. Overzicht

De standaard waarschuwingsweergave op iOS is geweldig, maar het is niet erg aanpasbaar in uiterlijk en gedrag. Als u een meldingsweergave nodig hebt die aanpasbaar is, moet u uw eigen oplossing maken en dat is wat we in deze zelfstudie zullen doen. De focus van deze zelfstudie ligt op het gedrag van de waarschuwingsweergave en niet zozeer op de functionaliteit ervan. Laten we eens kijken wat het resultaat is dat we zoeken

De waarschuwingsweergave is een UIView bijvoorbeeld waaraan we de volgende subweergaven toevoegen:

  • een UILabel object voor het weergeven van de titel van de waarschuwingsweergave
  • een UILabel object om het bericht van de waarschuwingsweergave weer te geven
  • een of meer UIButton instanties voor het laten communiceren van de gebruiker met de waarschuwingsweergave

We zullen de gebruiken UISnapBehavior klasse om de waarschuwingsweergave te presenteren. Zoals de naam al aangeeft, dit UIDynamicBehavior subklasse dwingt een dynamisch item naar een punt te snappen alsof het magnetisch ernaar is getrokken.

De UISnapBehavior klasse definieert een extra eigenschap, demping, die de hoeveelheid oscillatie definieert wanneer het dynamische item het punt heeft bereikt waarop het wordt aangetrokken.

We gebruiken een zwaartekrachtgedrag, in combinatie met een botsing en duwgedrag, om de waarschuwingsweergave te sluiten. Vergeet niet dat we dit gedrag al in de vorige tutorial hebben gebruikt.

De waarschuwingsweergave animeert vanaf de bovenkant van het scherm. Wanneer de waarschuwingsweergave verschijnt, zorgt het snapgedrag ervoor dat het in beeld komt en naar het midden van het scherm snapt. Om de waarschuwingsweergave te sluiten, duwt een duwgedrag hem even naar de onderkant van het scherm en een zwaartekrachtgedrag trekt hem dan naar de bovenkant van het scherm en laat hem buiten het scherm animeren.

We maken een aangepaste initialisatiemethode voor de component voor waarschuwingsweergave die de titel, het bericht, de knoptitels en de bovenliggende weergave van de waarschuwing accepteert. We zullen geen gedelegeerd protocol implementeren voor de waarschuwingsweergave. In plaats daarvan maken we gebruik van blokken, wat zorgt voor een meer elegante en moderne oplossing. Het blok of de handler accepteert twee parameters, de index en de titel van de knop waarop de gebruiker tikt.

We zullen ook een semi-transparante weergave achter de waarschuwingsweergave weergeven om te voorkomen dat de gebruiker in interactie gaat met de bovenliggende weergave zolang de waarschuwingsweergave zichtbaar is. Laten we beginnen met het bekijken van de eigenschappen van de waarschuwingsweergave en de aangepaste initialisatie.

2. Eigenschappen en initialisatie

Stap 1: De klasse Waarschuwingsweergave maken

druk op Command-N op uw toetsenbord om een ​​nieuw bestand te maken en te selecteren Objectieve C-klasse uit de lijst van iOS sjablonen. Maak er een subklasse van NSObject en noem het AlertComponent.

Stap 2: Eigenschappen declareren

De volgende stap is om een ​​paar privé-eigendommen te declareren. Open AlertComponent.m, voeg bovenaan een klasse-extensie toe en declareer de volgende eigenschappen:

@interface AlertComponent () @property (nonatomic, strong) UIView * alertView; @property (nonatomic, strong) UIView * backgroundView; @property (nonatomic, strong) UIView * targetView; @property (nonatomic, strong) UILabel * titleLabel; @property (nonatomic, strong) UILabel * messageLabel; @property (nonatomic, strong) UIDynamicAnimator * animator; @property (nonatomic, strong) NSString * title; @property (nonatomic, strong) NSString * -bericht; @property (nonatomic, strong) NSArray * buttonTitels; @property (nonatomic) CGRect initialAlertViewFrame; @einde

De functie van elke eigenschap wordt duidelijk als we de waarschuwingscomponent implementeren. Het is tijd om de aangepaste initialisatie van de component te maken.

Stap 3: Initialisatie

Zoals ik al zei, gaan we een aangepaste initialisatie gebruiken om het werken met de waarschuwingscomponent zo eenvoudig mogelijk te maken. De initializer accepteert vier parameters, de waarschuwingstitel, het bericht, de knoptitels en de weergave waaraan de waarschuwingscomponent wordt toegevoegd, de bovenliggende weergave. Open AlertComponent.h en voeg de volgende verklaring toe:

@interface AlertComponent: NSObject - (id) initAlertWithTitle: (NSString *) title andMessage: (NSString *) message andButtonTitles: (NSArray *) buttonTitels en TargetView: (UIView *) targetView; @einde

3. De alarmweergave instellen

Stap 1: Setup-methoden declareren

In dit deel wordt de waarschuwingsweergave ingesteld en worden alle subweergaven eraan toegevoegd. Ook worden de achtergrondweergave en de dynamische animator ingesteld.

Open AlertComponent.m en declareer de volgende privémethoden in de privéklasse-extensie:

@interface AlertComponent () ... - (ongeldig) setupBackgroundView; - (ongeldig) setupAlertView; @einde

De namen van de methoden spreken voor zich. Laten we beginnen met het implementeren van de setupAlertView methode eerst omdat de meeste instellingen van de waarschuwing plaatsvinden in deze methode.

Stap 2: De waarschuwingsweergave instellen

In setupAlertView, we doen drie dingen:

  • initialiseer en configureer de waarschuwingsweergave
  • initialiseer en configureer de labels van de waarschuwingsweergave
  • initialiseer en configureer de knoppen van de waarschuwingsweergave

Laten we beginnen met het berekenen van de grootte en positie van de waarschuwingsweergave zoals weergegeven in het onderstaande codefragment.

- (ongeldig) setupAlertView // Stel de grootte van de waarschuwingsweergave in. CGSize alertViewSize = CGSizeMake (250.0, 130.0 + 50.0 * self.buttonTitles.count); // Stel het oorspronkelijke oorsprongspunt in afhankelijk van de richting van de waarschuwingsweergave. CGPoint initialOriginPoint = CGPointMake (self.targetView.center.x, self.targetView.frame.origin.y - alertViewSize.height); 

We beginnen met het instellen van de grootte van de waarschuwingsweergave. Om de meldingsweergave dynamisch te maken, voegen we toe 50.0 wijst naar de hoogte voor elke knop. Merk ook op dat de oorspronkelijke oorsprong van de waarschuwingsweergave buiten het scherm valt. De volgende stap is het initialiseren en het instellen van de waarschuwingsweergave:

self.alertView = [[UIView-toewijzing] initWithFrame: CGRectMake (initialOriginPoint.x, initialOriginPoint.y, alertViewSize.width, alertViewSize.height)]; // Achtergrond kleur. [self.alertView setBackgroundColor: [UIColor colorWithRed: 0.94 green: 0.94 blue: 0.94 alpha: 1.0]]; // Maak de waarschuwingsweergave met afgeronde hoeken. [self.alertView.layer setCornerRadius: 10.0]; // Stel een rand in voor de waarschuwingsweergave. [self.alertView.layer setBorderWidth: 1.0]; [self.alertView.layer setBorderColor: [UIColor blackColor] .CGColor]; // Wijs het oorspronkelijke weergaveframe toe aan de betreffende eigenschap. self.initialAlertViewFrame = self.alertView.frame; 

Gebruik makend van alertViewSize en initialOriginPoint, we initialiseren de alertView object en stel de achtergrondkleur in. We rond de hoeken van de waarschuwingsweergave door het in te stellen laag's hoekradius naar 10.0, haar grensbreedte naar 1.0, en zijn rand kleur naar zwart. We slaan ook het eerste frame van de alertview op in zijn initialAlertViewFrame eigendom zoals we het later nodig hebben.

Als Xcode aangeeft dat het niet weet wat het is alertView's laag eigenschap, voeg vervolgens de volgende importinstructie toe bovenaan het implementatiebestand:

#importeren  

Het is tijd om de labels toe te voegen. Laten we beginnen met het titellabel.

// Stel het titellabel in. self.titleLabel = [[UILabel alloc] initWithFrame: CGRectMake (0.0, 10.0, self.alertView.frame.size.width, 40.0)]; [self.titleLabel setText: self.title]; [self.titleLabel setTextAlignment: NSTextAlignmentCenter]; [self.titleLabel setFont: [UIFont fontWithName: @ "Avenir-Heavy" -formaat: 14.0]]; // Voeg het titellabel toe aan de waarschuwingsweergave. [self.alertView addSubview: self.titleLabel];

Het instellen van het berichtlabel lijkt op elkaar.

// Stel het berichtlabel in. self.messageLabel = [[UILabel alloc] initWithFrame: CGRectMake (0.0, self.titleLabel.frame.origin.y + self.titleLabel.frame.size.height, self.alertView.frame.size.width, 80.0)]; [self.messageLabel setText: self.message]; [self.messageLabel setTextAlignment: NSTextAlignmentCenter]; [self.messageLabel setFont: [UIFont fontWithName: @ "Avenir" size: 14.0]]; [self.messageLabel setNumberOfLines: 3]; [self.messageLabel setLineBreakMode: NSLineBreakByWordWrapping]; // Voeg het berichtlabel toe aan de waarschuwingsweergave. [self.alertView addSubview: self.messageLabel];

Merk op dat de numberOfLines eigenschap is ingesteld op 3 en lineBreakMode ingesteld op NSLineBreakByWordWrapping.

Het laatste dat we moeten instellen zijn de knoppen van de waarschuwingsweergave. Hoewel het aantal knoppen kan variëren, is het instellen en positioneren van de knoppen vrij eenvoudig. We scheiden de knoppen door 5 punten en gebruik a voor loop om ze te initialiseren.

CGFloat lastSubviewBottomY = self.messageLabel.frame.origin.y + self.messageLabel.frame.size.height; voor (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; 

Merk op dat elke knop de handleButtonTap: methode wanneer erop wordt getikt. We kunnen bepalen op welke knop de gebruiker tikt door de knoppen te inspecteren label eigendom.

Voeg ten slotte de meldingsweergave toe aan de doel- of bovenliggende weergave door de volgende regel toe te voegen onder aan de SetupAlertView-methode:

// Voeg de waarschuwingsweergave toe aan de bovenliggende weergave. [self.targetView addSubview: self.alertView];

Stap 3: De achtergrondweergave instellen

De tweede methode die we moeten implementeren is setupBackgroundView. De achtergrondweergave zorgt ervoor dat de gebruiker geen interactie heeft met de bovenliggende weergave van de waarschuwingsweergave zolang de waarschuwingsweergave wordt weergegeven. We hebben in eerste instantie zijn alpha eigendom aan 0.0, wat betekent dat het transparant is.

- (void) setupBackgroundView self.backgroundView = [[UIView alloc] initWithFrame: self.targetView.frame]; [self.backgroundView setBackgroundColor: [UIColor grayColor]]; [self.backgroundView setAlpha: 0.0]; [self.targetView addSubview: self.backgroundView]; 

Stap 4: Implementatie van de initialisatie

Met setupAlertView en setupBackgroundView klaar voor gebruik, laten we de aangepaste initializer implementeren die we eerder hebben verklaard.

- (id) initAlertWithTitle: (NSString *) title andMessage: (NSString *) message andButtonTitles: (NSArray *) buttonTitles andTargetView: (UIView *) targetView if (self = [super init]) // Wijs de parameterwaarden toe aan lokale eigenschappen. self.title = titel; self.message = bericht; self.targetView = targetView; self.buttonTitles = buttonTitels; // Stel de achtergrondweergave in. [self setupBackgroundView]; // Stel de waarschuwingsweergave in. [self setupAlertView]; // Stel de animator in. self.animator = [[UIDynamicAnimator alloc] initWithReferenceView: self.targetView];  terugkeer zelf; 

We hebben de titel, bericht, targetView, en buttonTitles eigenschappen, aanroepen setupBackgroundView en setupAlertView, en initialiseer de dynamische animator, die binnenkomt self.targetView als referentie.

4. De waarschuwingsweergave weergeven

Om de waarschuwingsweergave weer te geven nadat deze is geïnitialiseerd, moeten we een openbare methode declareren en implementeren die kan worden aangeroepen door bijvoorbeeld de view-controller die de meldingsview host. Open AlertComponent.h en voeg de volgende methodeverklaring toe:

- (Void) showAlertView;

Ga terug naar AlertComponent.m implementeren showAlertView. Zoals ik eerder in deze tutorial al zei, zullen we een nieuwe gebruiken UIDynamicBehavior subklasse om de waarschuwingsweergave te tonen, UISnapBehavior. Laten we eens kijken hoe we deze klasse gebruiken showAlertView.

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

We beginnen met het verwijderen van bestaande dynamische gedragingen van de dynamische animator om ervoor te zorgen dat er geen conflicten opduiken. Vergeet niet dat sommige dynamische gedragingen slechts eenmaal aan de dynamische animator kunnen worden toegevoegd, zoals een zwaartekrachtgedrag. We voegen ook andere dynamische gedragingen toe om de waarschuwingsweergave te sluiten.

Zoals u kunt zien, is het gebruik van een snapgedrag niet moeilijk. We specificeren op welk dynamisch item het gedrag moet worden toegepast en stellen het punt in waarop het dynamische item moet klikken. We hebben ook de gedragingen ingesteld demping eigendom zoals we eerder hebben besproken. Merk ook op dat we het animeren alpha eigenschap van de achtergrondweergave.

Om de waarschuwingsweergave te testen, moeten we enkele wijzigingen aanbrengen in de ViewController klasse. Laten we beginnen met het toevoegen van een UIButton bijvoorbeeld naar de view van de view controller om de alert view te tonen. Open Main.storyboard en sleep een UIButton bijvoorbeeld van de Objectbibliotheek naar het zicht van de view controller. Plaats de knop onder aan de weergave en geef deze een titel van Toon waarschuwingsweergave. Voeg een actie toe aan ViewController.h zoals hieronder getoond.

@interface ViewController: UIViewController - (IBAction) showAlertView: (id) afzender; @einde

Ga terug naar het storyboard en sluit de actie van de view controller aan op de knop. Open ViewController.m en importeer het header-bestand van de AlertComponent klasse.

#import "AlertComponent.h"

Vervolgens declareert u een eigenschap in de privéklasse-extensie van het type AlertComponent en noem het alertComponent.

@interface ViewController () @property (nonatomic, strong) MenuComponent * menuComponent; @property (nonatomic, strong) AlertComponent * alertComponent; - (void) showMenu: (UIGestureRecognizer *) gestureRecognizer; @einde

Vervolgens initialiseren we de waarschuwingscomponent in de view controller's viewDidLoad methode.

- (void) viewDidLoad ... // Alarmcomponent initialiseren self.alertComponent = [[AlertComponent alloc] initAlertWithTitle: @ "Custom Alert" andMessage: @ "U hebt een nieuw e-mailbericht, maar ik weet niet van wie." andButtonTitles: @ [@ "Show me", @ "Kan me niet schelen", @ "Voor mij echt?"] andTargetView: self.view]; 

Om het waarschuwingsonderdeel te tonen, roept u aan showAlertView: in de actie die we zojuist hebben gemaakt, showAlertView:.

- (IBAction) showAlertView: (id) afzender [self.alertComponent showAlertView]; 

Voer uw toepassing uit en tik op de knop om de waarschuwingsweergave weer te geven. Het resultaat moet er ongeveer zo uitzien als hieronder.

5. De waarschuwingsweergave verbergen

Zoals we eerder zagen, de handleButtonTap: methode wordt aangeroepen wanneer de gebruiker op een knop van de waarschuwingsweergave tikt. De waarschuwingsweergave moet worden verborgen wanneer op een van de knoppen wordt getikt. Laten we kijken hoe dit werkt.

opnieuw bezoeken AlertComponent.m en, in de privéklasse-extensie, het handleButtonTap: methode.

@interface AlertComponent () ... - (ongeldig) handleButtonTap: (UIButton *) -zender; @einde

In deze methode maken we een aantal dynamische gedragingen en voegen deze toe aan het dynamische animatorobject. Het dynamische gedrag dat we nodig hebben, is:

  • een zwaartekrachtgedrag dat de waarschuwingsweergave naar de bovenkant van het scherm trekt
  • een botsingsgedrag met een buiten het scherm liggende grens die de waarschuwingsweergave stopt
  • een duwgedrag dat de waarschuwingsweergave enigszins richting de onderkant van het scherm geeft

Na het verwijderen van het bestaande gedrag van de dynamische animator en het pushgedrag initialiseren zoals hieronder getoond.

- (void) handleButtonTap: (UIButton *) afzender // Verwijder alle gedragingen van de animator. [self.animator removeAllBehaviors]; UIPushBehavior * pushBehavior = [[UIPushBehavior alloc] initWithItems: @ [self.alertView] modus: UIPushBehaviorModeInstantaneous]; [pushBehavior setAngle: M_PI_2 magnitude: 20.0]; [self.animator addBehavior: pushBehavior]; 

De hoek eigenschap van het duwgedrag bepaalt de richting van de push. Door de hoek in te stellen M_PI_2, de kracht van het duwgedrag wordt naar de onderkant van het scherm gericht.

De volgende stap is het toevoegen van het zwaartekrachtgedrag. De vector waar we doorheen gaan setGravityDirection zal resulteren in een kracht naar de bovenkant van het scherm, waardoor het waarschuwingsbeeld omhoog wordt getrokken.

UigravityBehavior * gravityBehavior = [[UIGravityBehavior alloc] initWithItems: @ [self.alertView]]; [gravityBehavior setGravityDirection: CGVectorMake (0.0, -1.0)]; [self.animator addBehavior: gravityBehavior];

Het interessante aan het botsgedrag is dat we een grens definiëren die buiten het scherm valt.

UICollisionBehavior * collisionBehavior = [[UICollisionBehavior alloc] initWithItems: @ [self.alertView]]; [collisionBehavior addBoundaryWithIdentifier: @ "alertCollisionBoundary" fromPoint: CGPointMake (self.initialAlertViewFrame.origin.x, self.initialAlertViewFrame.origin.y - 10.0) toPoint: CGPointMake (self.initialAlertViewFrame.origin.x + self.initialAlertViewFrame.size.width, self.initialAlertViewFrame.origin.y - 10.0)]; [self.animator addBehavior: collisionBehavior];

We hebben ook een dynamisch artikelgedrag nodig om de elasticiteit van de botsing in te stellen. Het resultaat is dat de waarschuwingsweergave een beetje kaatst wanneer deze botst met de buiten het scherm liggende grens.

UIDynamicItemBehavior * itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems: @ [self.alertView]]; item Behavior.elasticiteit = 0,4; [self.animator addBehavior: itemBehavior];

We moeten de achtergrondweergave ook weer transparant maken. We doen dit door de achtergrondweergave in te stellen alpha eigendom aan 0.0 in een animatieblok.

[UIView animateWithDuration: 2.0 animations: ^ [self.backgroundView setAlpha: 0.0]; ];

Voer uw toepassing nog een keer uit om het resultaat te bekijken.

6. Omgang met gebruikersinteractie

Hoewel de waarschuwingsweergave reageert op gebruikersinteractie, weten we momenteel niet op welke knop de gebruiker heeft getikt. Dat is waar we ons in dit gedeelte op zullen richten.

Zoals we deden met de menucomponent, gaan we blokken gebruiken om dit probleem op te lossen. Blokken zorgen voor een elegante oplossing en kunnen vaak eenvoudiger in gebruik zijn dan een gedelegeerd protocol.

We beginnen met het publiek bij te werken showAlertView methode. De methode moet een voltooiingshandler accepteren die de waarschuwingsweergave gebruikt als de gebruiker op een van de knoppen tikt. In AlertComponent.h, update de verklaring van de showAlertView methode van:

- (Void) showAlertView;

naar:

- (void) showAlertViewWithSelectionHandler: (void (^) (NSInteger-knopIndex, NSString * buttonTitle)) handler;

De voltooiingshandler accepteert twee parameters, de index, van het type NSInteger, en de titel, van het type NSString, van de knop die door de gebruiker is afgeluisterd. Als we de voltooiingsafhandelaar willen aanroepen wanneer de gebruiker op een knop van de waarschuwingsweergave tikt, moeten we een verwijzing naar de voltooiingshandler bijhouden. Dit betekent dat we een eigenschap voor de afhandelingsafhandelaar moeten declareren. We doen dit in de privéklasse-extensie in AlertComponent.m.

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

Nog steeds binnen AlertComponent.m, werk de methodebeschrijving bij zoals we onlangs in het headerbestand hebben gedaan en sla de voltooiingshandler op in de selectionHandler eigendom, wat we net hebben verklaard.

- (void) showAlertViewWithSelectionHandler: (void (^) (NSInteger, NSString *)) handler self.selectionHandler = handler; ...

Het laatste stukje van de puzzel roept de voltooiingshandler op handleButtonTap:, de tag en titel van de knop doorgeven.

- (ongeldig) handleButtonTap: (UIButton *) afzender // Bel de selectie-handler. self.selectionHandler (sender.tag, sender.titleLabel.text); ...

Het AlertComponent is voltooid. Het is tijd om alles te testen. Ga terug naar ViewController.m en update de showAlertView: actie zoals hieronder getoond. Zoals je kunt zien, roepen we het nieuwe aan showAlertViewWithSelectionHandler: methode en geef een blok door, dat wordt opgeroepen wanneer een knop in de waarschuwingsweergave wordt aangeraakt door de gebruiker.

- (IBAction) showAlertView: (id) afzender [self.alertComponent showAlertViewWithSelectionHandler: ^ (knop NSIntegerIndex, NSString * buttonTitle) NSLog (@ "% ld,% @", (long) buttonIndex, buttonTitle); ];  

Dat is het. Voer uw aanvraag nogmaals uit en inspecteer de console van Xcode om het resultaat van ons werk te zien.

Conclusie

UIKit Dynamics werd voor het eerst geïntroduceerd in iOS 7 en kan u helpen realistische animaties snel te maken. Deze korte reeks illustreert dat het gebruik van UIKit Dynamics in uw projecten niet moeilijk is en dat u geen expert hoeft te zijn in wiskunde of natuurkunde.

Merk op dat UIKit Dynamics in de eerste plaats is bedoeld voor gebruik in op view gebaseerde applicaties. Als je op zoek bent naar een vergelijkbare oplossing voor games, dan raad ik je aan om eens naar de Sprite Kit van Apple te kijken, die is gericht op het ontwikkelen van spellen..