Articles

iOS-animaties uitvoeren op weergaven met UIKit en UIView

  • 14 min lezen
  • Animatie,iOS,UI,Mobiele
  • Opgeslagen voor offline lezen
  • Delen op Twitter, LinkedIn
Dit artikel is bedoeld om een primer op iOS animaties uitvoerig ingaat op verschillende manieren doen. We beginnen met het begrijpen van de basisprincipes van animaties, verhuizen naar de kern Frameworks bouwen van een enkel voorbeeld met behulp van de verschillende methoden aangeboden en ten slotte kijken naar manieren om de prestaties af te stemmen.

Ik ben al meer dan een decennium ontwikkelaar van iOS en heb zelden artikelen gezien die alle mogelijke manieren om animaties in iOS uit te voeren consolideren. Dit artikel is bedoeld om een primer op iOS animaties met de bedoeling van uitputtend die de verschillende manieren om hetzelfde te doen.

gezien de omvang van het onderwerp, zouden we elk deel bondig op een vrij hoog niveau behandelen. Het doel is om de lezer te onderwijzen met een set van keuzes om animaties toe te voegen aan zijn/ haar iOS-app.

voordat we beginnen met onderwerpen gerelateerd aan iOS, laten we eerst even kijken naar de animatiesnelheid.

animeren met 60 FPS

over het algemeen wordt in video ‘ s elk frame weergegeven door een afbeelding en de framesnelheid bepaalt het aantal gespiegelde afbeeldingen in de reeks. Dit wordt aangeduid als ‘frames per seconde’ of FPS.

FPS bepaalt het aantal stilstaande beelden dat binnen een seconde wordt omgedraaid, wat letterlijk betekent dat hoe meer het aantal afbeeldingen / frames, meer details / informatie worden weergegeven in de video. Dit geldt ook voor animaties.

FPS wordt meestal gebruikt om de kwaliteit van animaties te bepalen. Er is een populaire mening dat een goede animatie moet draaien op 60fps of hoger — iets minder dan 60fps zou voelen een beetje off.

wilt u het verschil zien tussen 30FPS en 60FPS? Moet je dit zien.

merkte u het verschil? Menselijke ogen kunnen zeker de jitter voelen bij lagere fps. Daarom is het altijd een goede gewoonte om ervoor te zorgen dat elke animatie die u maakt, zich houdt aan de basisregel van het draaien op 60FPS of hoger. Dit maakt het gevoel realistischer en levendiger.

nu we naar FPS hebben gekeken, gaan we dieper in op de verschillende core iOS frameworks die ons een manier bieden om animaties uit te voeren.

Core Frameworks

In deze sectie zullen we ingaan op de frameworks in de iOS SDK die gebruikt kunnen worden voor het maken van weergaveanimaties. We zullen een korte wandeling door elk van hen, het uitleggen van hun feature set met een relevant voorbeeld.

UIKit / UIView animaties

UIView is de basisklasse voor elke weergave die inhoud in iOS-apps weergeeft.

UIKit, het framework dat ons UIView geeft, biedt ons al enkele basis animatiefuncties die het voor ontwikkelaars gemakkelijk maken om meer te bereiken door minder te doen.

de API, UIView.animate, is de makkelijkste manier om weergaven te animeren, omdat de eigenschappen van elke weergave gemakkelijk geanimeerd kunnen worden door de eigenschapswaarden in de op blokken gebaseerde syntaxis op te geven.

in UIKit-animaties wordt aanbevolen om alleen de animeerbare eigenschappen van UIVIew aan te passen, anders zullen er repercussies zijn waarbij de animaties de weergave in een onverwachte toestand kunnen brengen.

animatie(withDuration: animations: completion)

deze methode neemt de animatieduur in, een set van de animeerbare eigenschappen van de weergave die geanimeerd moeten worden. Het completion block geeft een callback wanneer de weergave klaar is met het uitvoeren van de animatie.

bijna elke vorm van animatie zoals verplaatsen, schalen, roteren, vervagen, enz. on a view kan worden bereikt met deze enkele API.

bedenk nu dat u een wijziging in de grootte van een knop wilt animeren of dat u een bepaalde weergave in het scherm wilt inzoomen. Dit is hoe we het kunnen doen met behulp van deUIView.animate API:

let newButtonWidth: CGFloat = 60UIView.animate(withDuration: 2.0) { //1 self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth) //2 self.button.center = self.view.center //3}

Hier is wat we hier aan het doen zijn:

  1. we noemen de UIView.animate methode met een tijdswaarde die eraan wordt doorgegeven die aangeeft hoe lang de animatie, beschreven in het blok, moet draaien.
  2. we stellen het nieuwe frame van de knop in dat de uiteindelijke status van de animatie moet vertegenwoordigen.
  3. we stellen de knop center in met het centrum van superview, zodat deze in het midden van het scherm blijft.

het bovenstaande blok animatie code moet de animatie van de knop frame veranderen van het huidige frame activeren:

Width = 0, Height = 0

naar het uiteindelijke frame:

Width = Height = newButtonWidth

en zo ziet de animatie eruit:

animatewith duration

deze methode is als een uitbreiding van de animate methode waar u alles kunt doen wat u kunt uitvoeren in de voorgaande API met een aantal fysica gedrag toegevoegd aan de weergave animaties.

bijvoorbeeld, als u de veerdemping effecten wilt bereiken in de animatie die we hierboven hebben gedaan, dan is dit hoe de code eruit zou zien:

let newButtonWidth: CGFloat = 60UIView.animate(withDuration: 1.0, //1 delay: 0.0, //2 usingSpringWithDamping: 0.3, //3 initialSpringVelocity: 1, //4 options: UIView.AnimationOptions.curveEaseInOut, //5 animations: ({ //6 self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth) self.button.center = self.view.center}), completion: nil)

Hier is de set van parameters die we gebruiken:

  1. duration
    geeft de duur van de animatie weer die bepaalt hoe lang het blok code moet draaien.
  2. delay
    vertegenwoordigt de initiële vertraging die we willen hebben voor het begin van de animatie.
  3. SpringWithDamping
    vertegenwoordigt de waarde van het veerkrachtige effect dat we willen dat de weergave zich gedraagt. De waarde moet tussen 0 en 1 liggen. Hoe lager de waarde, hoe hoger de veertrilling.
  4. velocity
    geeft de snelheid weer waarmee de animatie moet starten.
  5. options
    type animatiecurve dat u wilt toepassen op uw weergaveanimatie.
  6. tot slot, het blok code waar we het frame van de knop Instellen die geanimeerd moet worden. Het is hetzelfde als de vorige animatie.

en zo ziet de animatie eruit met de bovenstaande animatieconfiguratie:

UIViewPropertyAnimator

voor een beetje meer controle over animaties is UIViewPropertyAnimator handig als het ons een manier biedt om te pauzeren en te hervatten animaties. U kunt aangepaste timing hebben en uw animatie interactief en onderbreekbaar te zijn. Dit is erg handig bij het uitvoeren van animaties die ook interactief zijn met acties van gebruikers.

het klassieke gebaar ‘Slide To Unlock’ en de animatie voor afzetting/ uitvouwen van de speler (in de Muziek-app) zijn voorbeelden van interactieve en onderbreekbare animaties. U kunt beginnen met het verplaatsen van een uitzicht met uw vinger, laat het dan los en het uitzicht gaat terug naar de oorspronkelijke positie. Als alternatief kunt u de weergave tijdens de animatie te vangen en verder te slepen met uw vinger.

Hier volgt een eenvoudig voorbeeld van hoe we de animatie kunnen bereiken met UIViewPropertyAnimator:

let newButtonWidth: CGFloat = 60let animator = UIViewPropertyAnimator(duration:0.3, curve: .linear) { //1 self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth) self.button.center = self.view.center}animator.startAnimation() //2

Hier is wat we doen:

  1. we noemen de UIViewProperty API door de duur en de animatiecurve te passeren.
  2. In tegenstelling tot beide bovenstaande UIView.animate API ‘ s, de animatie zal niet starten, tenzij je het specificeert door jezelf dat wil zeggen Je bent in de volledige controle van de volledige animatie proces/ flow.

stel nu dat je nog meer controle wilt over de animaties. U wilt bijvoorbeeld elk frame in de animatie ontwerpen en beheren. Daar is een andere API voor, animateKeyframes. Maar voordat we er dieper op ingaan, laten we snel kijken naar wat een frame is, in een animatie.

Wat Is een frame?

een verzameling van de framewijzigingen/ overgangen van de weergave, van de begintoestand naar de eindtoestand, wordt gedefinieerd als animation en elke positie van de weergave tijdens de animatie wordt aangeroepen als een frame.

animateKeyframes

deze API biedt een manier om de animatie zo te ontwerpen dat u meerdere animaties met verschillende timings en overgangen kunt definiëren. Post dit, de API integreert gewoon alle animaties in een naadloze ervaring.

laten we zeggen dat we onze knop op een willekeurige manier op het scherm willen verplaatsen. Laten we eens kijken hoe we de keyframe animation API kunnen gebruiken om dit te doen.

UIView.animateKeyframes(withDuration: 5, //1 delay: 0, //2 options: .calculationModeLinear, //3 animations: { //4 UIView.addKeyframe( //5 withRelativeStartTime: 0.25, //6 relativeDuration: 0.25) { //7 self.button.center = CGPoint(x: self.view.bounds.midX, y: self.view.bounds.maxY) //8 } UIView.addKeyframe(withRelativeStartTime: 0.5, relativeDuration: 0.25) { self.button.center = CGPoint(x: self.view.bounds.width, y: start.y) } UIView.addKeyframe(withRelativeStartTime: 0.75, relativeDuration: 0.25) { self.button.center = start }})

Hier is de uitsplitsing:

  1. duration
    roep de API aan door de duur van de animatie door te geven.
  2. delay
    initiële vertraging duur van de animatie.
  3. options
    het type animatiecurve dat u wilt toepassen op uw beeldanimatie.
  4. animations
    Blok dat alle keyframe-animaties neemt die zijn ontworpen door de ontwikkelaar/ gebruiker.
  5. addKeyFrame
    roep de API aan om elke animatie te ontwerpen. In ons geval hebben we elke beweging van de knop gedefinieerd. We kunnen zoveel animaties als we nodig hebben, toegevoegd aan het blok.
  6. relativeStartTime
    definieert de starttijd van de animatie in de verzameling van het animatieblok.
  7. relativeDuration
    definieert de totale duur van deze specifieke animatie.
  8. center
    in ons geval veranderen we gewoon de middeneigenschap van de knop om de knop rond het scherm te verplaatsen.

en zo ziet de uiteindelijke animatie eruit:

Coreanimatie

elke op UIKit gebaseerde animatie wordt intern vertaald in kernanimaties. Dus, de Core Animation framework fungeert als een backing layer of backbone voor elke UIKit animatie. Vandaar, alle UIKit animatie API ’s zijn niets anders dan ingekapselde lagen van de kern animatie API’ s in een gemakkelijk te consumeren of handige manier.

UIKit animatie API ‘ s bieden niet veel controle over animaties die zijn uitgevoerd over een weergave, omdat ze meestal worden gebruikt voor animeerbare eigenschappen van de weergave. Vandaar dat in dergelijke gevallen, waar u van plan bent om de controle over elk frame van de animatie hebben, is het beter om de onderliggende kern animatie API ‘ s direct te gebruiken. Als alternatief kunnen zowel de UIView-animaties als de core-animaties in combinatie worden gebruikt.

UIView + Core Animation

laten we eens kijken hoe we dezelfde knop veranderen animatie opnieuw kunnen maken samen met het specificeren van de timing curve met behulp van de UIView en Core animatie API ‘ s.

we kunnen CATransaction’s timingfuncties gebruiken, waarmee u de animatiecurve kunt specificeren en beheren.

laten we eens kijken naar een voorbeeld van een animatie voor het wijzigen van de grootte van een knop met de hoekradius die gebruik maakt van deCATransaction’s timing functie en een combinatie van UIView animaties:

let oldValue = button.frame.width/2let newButtonWidth: CGFloat = 60/* Do Animations */CATransaction.begin() //1CATransaction.setAnimationDuration(2.0) //2CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)) //3// View animations //4UIView.animate(withDuration: 1.0) { self.button.frame = CGRect(x: 0, y: 0, width: newButtonWidth, height: newButtonWidth) self.button.center = self.view.center}// Layer animationslet cornerAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.cornerRadius)) //5cornerAnimation.fromValue = oldValue //6cornerAnimation.toValue = newButtonWidth/2 //7button.layer.cornerRadius = newButtonWidth/2 //8button.layer.add(cornerAnimation, forKey: #keyPath(CALayer.cornerRadius)) //9CATransaction.commit() //10

Hier is de uitsplitsing:

  1. begin
    vertegenwoordigt het begin van het animatiecodeblok.
  2. duration
    Totale animatieduur.
  3. curve
    geeft de timingcurve weer die op de animatie moet worden toegepast.
  4. UIView.animate
    Onze eerste animatie om het frame van de knop te veranderen.
  5. CABasicAnimation
    We maken het CABasicAnimation object door het cornerRadius van de knop te verwijzen als het toetsenbord aangezien dat is wat we willen animeren. Op dezelfde manier, als je granulair niveau controle wilt hebben over de keyframe animaties, dan kun je de CAKeyframeAnimation Klasse gebruiken.
  6. fromValue
    vertegenwoordigt de beginwaarde van de animatie, d.w.z. de initiële cornerRadius waarde van de knop waar de animatie moet beginnen.
  7. toValue
    vertegenwoordigt de uiteindelijke waarde van de animatie, d.w.z. de uiteindelijke cornerRadius waarde van de knop waar de animatie moet eindigen.
  8. cornerRadius
    We moeten de eigenschap cornerRadius van de knop Instellen met de uiteindelijke waarde van de animatie anders wordt de cornerRadius waarde van de knop automatisch teruggezet naar de oorspronkelijke waarde nadat de animatie is voltooid.
  9. addAnimation
    We voegen het animatieobject dat de configuratie van het gehele animatieproces bevat aan de laag toe door het toetsenbord te representeren waarvoor de animatie moet worden uitgevoerd.
  10. commit
    vertegenwoordigt het einde van het animatiecodeblok en start de animatie.

Dit is hoe de uiteindelijke animatie eruit zou zien:

deze blog is een geweldige leesfunctie om meer geavanceerde animaties te maken, aangezien het u netjes door de meeste Core Animation framework Api ‘ s loopt met instructies die u door elke stap van de weg.

UIKitDynamics

UIKit Dynamics is de fysica-engine voor UIKit die u in staat stelt om elk fysisch gedrag zoals botsingen, zwaartekracht, push, snap, etc, toe te voegen aan de UIKit-besturingselementen.

UIKitDynamicAnimator

Dit is de admin klasse van het UIKit Dynamics framework dat alle animaties reguleert die door een bepaalde UI-besturing worden geactiveerd.

UIKitDynamicBehavior

Het stelt u in staat om elk fysisch gedrag toe te voegen aan een animator die het vervolgens in staat stelt om uit te voeren op de weergave die eraan is gekoppeld.

verschillende soorten gedrag voor UIKitDynamics omvatten:

  • UIAttachmentBehavior
  • UICollisionBehavior
  • UIFieldBehavior
  • UIGravityBehavior
  • UIPushBehavior
  • UISnapBehavior

De architectuur van UIKitDynamics ziet er zo uit. Merk op dat de Items 1 tot en met 5 kunnen worden vervangen door een enkele weergave.

laten we wat fysica gedrag toepassen op onze knop. We zullen zien hoe we de zwaartekracht op de knop kunnen toepassen zodat het ons een gevoel geeft om met een echt object om te gaan.

var dynamicAnimator : UIDynamicAnimator!var gravityBehavior : UIGravityBehavior!dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1gravityBehavior = UIGravityBehavior(items: ) //2dynamicAnimator.addBehavior(gravityBehavior) //3

Hier is de uitsplitsing:

  1. UIKitDynamicAnimator
    We hebben een UIKitDynamicAnimator object gemaakt dat fungeert als orkestrator voor het uitvoeren van animaties. We hebben ook de superview van onze button als referentieweergave doorgegeven.
  2. UIGravityBehavior
    We hebben een UIGravityBehavior object aangemaakt en onze knop doorgegeven aan de array-elementen waarop dit gedrag wordt geïnjecteerd.
  3. addBehavior
    We hebben het gravity object aan de animator toegevoegd.
    Dit zou een animatie moeten maken zoals hieronder getoond:
    merk op hoe de knop van het midden (de oorspronkelijke positie) van het scherm naar beneden en verder valt.

    we moeten de animator vertellen om de onderkant van het scherm als de grond te beschouwen. Dit is waar UICollisionBehavior in beeld komt.

    var dynamicAnimator : UIDynamicAnimator!var gravityBehavior : UIGravityBehavior!var collisionBehavior : UICollisionBehavior!dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1gravityBehavior = UIGravityBehavior(items: ) //2dynamicAnimator.addBehavior(gravityBehavior) //3collisionBehavior = UICollisionBehavior(items: ) //4collisionBehavior.translatesReferenceBoundsIntoBoundary = true //5dynamicAnimator.addBehavior(collisionBehavior) //6
  4. UICollisionBehavior
    We hebben een UICollisionBehavior object aangemaakt en langs de knop doorgegeven zodat het gedrag aan het element wordt toegevoegd.
  5. translatesReferenceBoundsIntoBoundary
    Het inschakelen van deze eigenschap vertelt de animator om de grens van referentieweergaven als het einde te nemen, wat in ons geval de onderkant van het scherm is.
  6. addBehavior
    hier hebben we botsingsgedrag aan de animator toegevoegd.
    nu zou onze knop de grond moeten raken en stil moeten staan zoals hieronder getoond:

    dat is vrij netjes, nietwaar?
    laten we nu proberen een stuiterend effect toe te voegen zodat ons object realistischer aanvoelt. Om dat te doen, zullen we de UIDynamicItemBehavior Klasse gebruiken.

    var dynamicAnimator : UIDynamicAnimator!var gravityBehavior : UIGravityBehavior!var collisionBehavior : UICollisionBehavior!var bouncingBehavior : UIDynamicItemBehavior!dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1gravityBehavior = UIGravityBehavior(items: ) //2dynamicAnimator.addBehavior(gravityBehavior) //3collisionBehavior = UICollisionBehavior(items: ) //4collisionBehavior.translatesReferenceBoundsIntoBoundary = true //5dynamicAnimator.addBehavior(collisionBehavior) //6//Adding the bounce effectbouncingBehavior = UIDynamicItemBehavior(items: ) //7bouncingBehavior.elasticity = 0.75 //8dynamicAnimator.addBehavior(bouncingBehavior) //9
  7. UIDynamicItemBehavior
    We hebben een UIDynamicItemBehavior object aangemaakt en langs de knop doorgegeven zodat het gedrag aan het element wordt toegevoegd.
  8. elasticity
    waarde moet tussen 0-1 liggen, het vertegenwoordigt de elasticiteit, d.w.z. het aantal keren dat het object op en van de grond moet stuiteren wanneer het wordt geraakt. Dit is waar de magie gebeurt – door het aanpassen van deze eigenschap, kunt u onderscheid maken tussen verschillende soorten objecten zoals ballen, flessen, harde voorwerpen en ga zo maar door.
  9. addBehavior
    hier hebben we botsingsgedrag aan de animator toegevoegd.

nu moet onze knop stuiteren als het de grond raakt zoals hieronder getoond:

deze repo is heel nuttig en toont alle UIKitDynamics gedrag in actie. Het biedt ook broncode om te spelen met elk gedrag. Dat, naar mijn mening, moet dienen als een uitgebreide lijst van manieren om iOS-animaties uit te voeren op views!

in de volgende sectie zullen we een korte blik werpen op de tools die ons zullen helpen bij het meten van de prestaties van animaties. Ik zou u ook aanraden om te kijken naar manieren om uw Xcode build te optimaliseren, omdat het een enorme hoeveelheid van uw ontwikkeling tijd zal besparen.

Performance Tuning

In deze sectie zullen we kijken naar manieren om de prestaties van iOS-animaties te meten en af te stemmen. Als iOS-ontwikkelaar hebt u misschien al Xcode-instrumenten gebruikt, zoals geheugenlekken en toewijzingen voor het meten van de prestaties van de algehele app. Ook zijn er instrumenten die kunnen worden gebruikt om de prestaties van animaties te meten.

Core Animation Instrument

probeer het Core Animation instrument en u kunt de FPS zien die uw app-scherm levert. Dit is een geweldige manier om de prestaties/ snelheid van een animatie weergegeven in uw iOS-app te meten.

tekening

FPS is sterk verlaagd in de app die zware inhoud zoals afbeeldingen met effecten zoals schaduwen weergeeft. In dergelijke gevallen, in plaats van het toewijzen van de afbeelding direct aan de UIImageView’s image eigenschap, proberen om de afbeelding afzonderlijk te tekenen in een context met behulp van Core Graphics API’ s. Dit vermindert de weergavetijd van het beeld door de decompressielogica asynchroon uit te voeren wanneer dit gebeurt in een aparte thread in plaats van de hoofdthread.

Rasterisatie

Rasterisatie is een proces dat wordt gebruikt om complexe laaginformatie te cachen, zodat deze weergaven niet opnieuw worden getekend wanneer ze worden gerenderd. Het opnieuw tekenen van weergaven is de belangrijkste oorzaak van de vermindering van FPS en daarom is het het beste om rasterisatie toe te passen op weergaven die meerdere keren worden hergebruikt.

het afronden van

tot slot heb ik ook een lijst van nuttige bronnen voor iOS-animaties samengevat. U vindt dit misschien erg handig bij het werken aan iOS-animaties. Daarnaast kunt u deze set van ontwerptools ook nuttig vinden als een (ontwerp) stap voordat u zich verdiept in animaties.