Ausführen von iOS-Animationen auf Ansichten mit UIKit und UIView
- Über den Autor
- Animieren mit 60 FPS
- Core Frameworks
- UIKit/ UIView Animations
- animation(withDuration: animations: completion)
- animateWithDuration
- UIViewPropertyAnimator
- Was ist ein frame?
- animateKeyframes
- CoreAnimation
- UIView + Core Animation
- UIKitDynamics
- UIKitDynamicAnimator
- UIKitDynamicBehavior
- Leistungsoptimierung
- Core Animation Instrument
- Zeichnen
- Rasterisierung
- Einpacken
Über den Autor
Saravanan ist iOS-Ingenieur und Autor bei Flexiple und Remote Tools. Er hat mit mehreren Startups in verschiedenen Bereichen zusammengearbeitet.Mehr übersaravanan↬
- 14 min lesen
- Animation, iOS, UI, Mobile
- Zum Offline-Lesen gespeichert
- Teilen auf Twitter, LinkedIn
Ich bin seit über einem Jahrzehnt iOS-Entwickler und habe selten Artikel gesehen, in denen alle möglichen Möglichkeiten zum Ausführen von Animationen in iOS zusammengefasst sind. Dieser Artikel soll eine Einführung in iOS-Animationen geben, um die verschiedenen Möglichkeiten, dies zu tun, umfassend zu behandeln.
Angesichts des Umfangs des Themas würden wir jeden Teil kurz und bündig auf einem ziemlich hohen Niveau behandeln. Ziel ist es, dem Leser eine Reihe von Möglichkeiten zu bieten, Animationen zu seiner iOS-App hinzuzufügen.
Bevor wir mit iOS-Themen beginnen, werfen wir einen kurzen Blick auf die Animationsgeschwindigkeit.
Animieren mit 60 FPS
Im Allgemeinen wird in Videos jedes Bild durch ein Bild dargestellt, und die Bildrate bestimmt die Anzahl der in der Sequenz gespiegelten Bilder. Dies wird als ‚Frames pro Sekunde‘ oder FPS bezeichnet.
FPS bestimmt die Anzahl der Standbilder, die innerhalb einer Sekunde gespiegelt werden, was wörtlich bedeutet, dass je mehr Bilder / Frames vorhanden sind, desto mehr Details / Informationen werden im Video angezeigt. Dies gilt auch für Animationen.
FPS wird normalerweise verwendet, um die Qualität von Animationen zu bestimmen. Es gibt eine populäre Meinung, dass jede gute Animation mit 60fps oder höher laufen sollte — alles, was weniger als 60fps wäre, würde sich ein bisschen daneben anfühlen.
Möchten Sie den Unterschied zwischen 30FPS und 60FPS sehen? Überprüfen Sie dies!
Haben Sie den Unterschied bemerkt? Menschliche Augen können den Jitter bei niedrigeren fps definitiv spüren. Daher ist es immer eine gute Praxis, um sicherzustellen, dass jede Animation, die Sie erstellen, hält sich an die Grundregel der Ausführung bei 60FPS oder höher. Dadurch fühlt es sich realistischer und lebendiger an.
Nachdem wir uns FPS angesehen haben, wollen wir uns nun mit den verschiedenen Kern-iOS-Frameworks befassen, die uns eine Möglichkeit bieten, Animationen auszuführen.
Core Frameworks
In diesem Abschnitt werden wir auf die Frameworks im iOS SDK eingehen, die zum Erstellen von Ansichtsanimationen verwendet werden können. Wir werden einen kurzen Spaziergang durch jeden von ihnen machen und ihre Funktionen anhand eines relevanten Beispiels erklären.
UIKit/ UIView Animations
UIView ist die Basisklasse für jede Ansicht, die Inhalte in iOS-Apps anzeigt.
UIKit, das Framework, das uns UIView gibt, bietet uns bereits einige grundlegende Animationsfunktionen, mit denen Entwickler mit weniger Aufwand mehr erreichen können.
Die API UIView.animate
ist der einfachste Weg, Ansichten zu animieren, da die Eigenschaften jeder Ansicht einfach animiert werden können, indem die Eigenschaftswerte in der blockbasierten Syntax bereitgestellt werden.
In UIKit-Animationen wird empfohlen, nur die animierbaren Eigenschaften von UIView zu ändern, da sonst Auswirkungen auftreten, bei denen die Animationen dazu führen können, dass die Ansicht in einen unerwarteten Zustand gerät.
animation(withDuration: animations: completion)
Diese Methode nimmt die Animationsdauer auf, eine Reihe von animierbaren Eigenschaftsänderungen der Ansicht, die animiert werden müssen. Der Abschlussblock gibt einen Rückruf aus, wenn die Ansicht mit dem Ausführen der Animation fertig ist.
Fast jede Art von Animation wie Verschieben, Skalieren, Drehen, Verblassen usw. auf einer Ansicht kann mit dieser einzigen API erreicht werden.
Bedenken Sie nun, dass Sie eine Änderung der Schaltflächengröße animieren oder eine bestimmte Ansicht in den Bildschirm zoomen möchten. So können wir es mit der UIView.animate
API machen:
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}
Folgendes machen wir hier:
- Wir rufen die
UIView.animate
-Methode mit einem übergebenen duration-Wert auf, der angibt, wie lange die im Block beschriebene Animation ausgeführt werden soll. - Wir setzen den neuen Frame der Schaltfläche, der den Endzustand der Animation darstellen soll.
- Wir setzen den Button
center
mit seiner Superview-Mitte so, dass er in der Mitte des Bildschirms bleibt.
Der obige Block des Animationscodes sollte die Animation des Frames der Schaltfläche auslösen, der vom aktuellen Frame wechselt:
Width = 0, Height = 0
Zum letzten Frame:
Width = Height = newButtonWidth
Und so würde die Animation aussehen:
animateWithDuration
Diese Methode ist wie eine Erweiterung der Animate-Methode, bei der Sie alles tun können, was Sie in der vorherigen API ausführen können, wobei den View-Animationen einige physikalische Verhaltensweisen hinzugefügt wurden.
Wenn Sie beispielsweise Federdämpfungseffekte in der Animation erzielen möchten, die wir oben ausgeführt haben, würde der Code folgendermaßen aussehen:
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 ist der Parametersatz, den wir verwenden:
-
duration
Stellt die Dauer der Animation dar und bestimmt, wie lange der Codeblock ausgeführt werden soll. -
delay
Stellt die anfängliche Verzögerung dar, die wir vor dem Start der Animation haben möchten. -
SpringWithDamping
Repräsentiert den Wert des federnden Effekts, den die Ansicht haben soll. Der Wert muss zwischen 0 und 1 liegen. Je niedriger der Wert, desto höher die Federschwingung. -
velocity
Stellt die Geschwindigkeit dar, mit der die Animation gestartet werden soll. -
options
Art der Animationskurve, die Sie auf Ihre Ansichtsanimation anwenden möchten. - Schließlich der Codeblock, in dem wir den Rahmen der Schaltfläche festlegen, die animiert werden muss. Es ist das gleiche wie die vorherige Animation.
Und so würde die Animation mit der obigen Animationskonfiguration aussehen:
UIViewPropertyAnimator
Für ein bisschen mehr Kontrolle über Animationen, UIViewPropertyAnimator
ist praktisch, wo es uns eine Möglichkeit bietet, zu pausieren und animationen fortsetzen. Sie können ein benutzerdefiniertes Timing festlegen und Ihre Animation interaktiv und unterbrechbar gestalten. Dies ist sehr hilfreich, wenn Animationen ausgeführt werden, die auch mit Benutzeraktionen interagierbar sind.
Die klassische ‚Slide to Unlock‘-Geste und die Player-Ansicht Dismiss/ Expand-Animation (in der Musik-App) sind Beispiele für interaktive und unterbrechbare Animationen. Sie können eine Ansicht mit dem Finger bewegen, dann loslassen und die Ansicht kehrt in ihre ursprüngliche Position zurück. Alternativ können Sie die Ansicht während der Animation erfassen und mit dem Finger weiterziehen.
Es folgt ein einfaches Beispiel, wie wir die Animation mit UIViewPropertyAnimator
erreichen könnten:
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 ist, was wir tun:
- Wir rufen die
UIViewProperty
API auf, indem wir die Dauer und die Animationskurve übergeben. - Im Gegensatz zu den beiden oben genannten UIView .animieren Sie APIs, die Animation wird nur gestartet, wenn Sie sie selbst angeben, dh Sie haben die volle Kontrolle über den gesamten Animationsprozess / -ablauf.
Angenommen, Sie möchten noch mehr Kontrolle über die Animationen. Sie möchten beispielsweise jeden einzelnen Frame in der Animation entwerfen und steuern. Es gibt eine andere API dafür, animateKeyframes
. Aber bevor wir uns damit befassen, schauen wir uns kurz an, was ein Frame in einer Animation ist.
Was ist ein frame
?
Eine Sammlung der Bildänderungen/ Übergänge der Ansicht vom Startzustand zum Endzustand wird als animation
definiert und jede Position der Ansicht während der Animation wird als frame
.
animateKeyframes
Diese API bietet eine Möglichkeit, die Animation so zu gestalten, dass Sie mehrere Animationen mit unterschiedlichen Timings und Übergängen definieren können. Danach integriert die API einfach alle Animationen in ein nahtloses Erlebnis.
Nehmen wir an, wir möchten unsere Schaltfläche zufällig auf dem Bildschirm verschieben. Mal sehen, wie wir dazu die Keyframe-Animations-API verwenden können.
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 ist die Aufschlüsselung:
-
duration
Rufen Sie die API auf, indem Sie die Dauer der Animation übergeben. -
delay
Anfängliche Verzögerungsdauer der Animation. -
options
Die Art der Animationskurve, die Sie auf Ihre Ansichtsanimation anwenden möchten. -
animations
Block, der alle vom Entwickler / Benutzer entworfenen Keyframe-Animationen aufnimmt. -
addKeyFrame
Rufen Sie die API auf, um jede einzelne Animation zu entwerfen. In unserem Fall haben wir jede Bewegung der Schaltfläche definiert. Wir können dem Block so viele solcher Animationen hinzufügen, wie wir benötigen. -
relativeStartTime
Definiert die Startzeit der Animation in der Sammlung des Animationsblocks. -
relativeDuration
Definiert die Gesamtdauer dieser spezifischen Animation. -
center
In unserem Fall ändern wir einfach die Center-Eigenschaft der Schaltfläche, um die Schaltfläche auf dem Bildschirm zu verschieben.
Und so sehen die endgültigen Animationen aus:
CoreAnimation
Jede UIKit-basierte Animation wird intern in Core-Animationen übersetzt. Somit fungiert das Core Animation Framework als Backing Layer oder Backbone für jede UIKit-Animation. Daher sind alle UIKit-Animations-APIs nichts anderes als gekapselte Ebenen der Kernanimations-APIs auf leicht konsumierbare oder bequeme Weise.
UIKit-Animations-APIs bieten nicht viel Kontrolle über Animationen, die über eine Ansicht ausgeführt wurden, da sie hauptsächlich für animierbare Eigenschaften der Ansicht verwendet werden. In solchen Fällen, in denen Sie die Kontrolle über jeden Frame der Animation haben möchten, ist es daher besser, die zugrunde liegenden Kernanimations-APIs direkt zu verwenden. Alternativ können sowohl die UIView-Animationen als auch die Core-Animationen in Verbindung verwendet werden.
UIView + Core Animation
Mal sehen, wie wir dieselbe Schaltflächenänderungsanimation zusammen mit der Angabe der Zeitkurve mithilfe der UIView- und Core Animation-APIs neu erstellen können.
Wir können die Timing-Funktionen von CATransaction
verwenden, mit denen Sie die Animationskurve angeben und steuern können.
Schauen wir uns ein Beispiel für eine Animation zum Ändern der Schaltflächengröße mit ihrem Eckenradius an, die die Timing-Funktion von CATransaction
und eine Kombination von UIView-Animationen verwendet:
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 ist die Aufschlüsselung:
-
begin
Stellt den Anfang des Animationscodeblocks dar. -
duration
Gesamtdauer der Animation. -
curve
Stellt die Zeitkurve dar, die auf die Animation angewendet werden muss. -
UIView.animate
Unsere erste Animation, um den Rahmen der Schaltfläche zu ändern. -
CABasicAnimation
Wir erstellen dasCABasicAnimation
-Objekt, indem wir diecornerRadius
der Schaltfläche als Tastaturpfad verwenden, da wir dies animieren möchten. Wenn Sie eine detaillierte Kontrolle über die Keyframe-Animationen haben möchten, können Sie die KlasseCAKeyframeAnimation
. -
fromValue
Stellt den Startwert der Animation dar, d.h. den initialencornerRadius
Wert der Schaltfläche, von der aus die Animation beginnen muss. -
toValue
Repräsentiert den endgültigen Wert der Animation, d.h. den endgültigencornerRadius
Wert der Schaltfläche, auf der die Animation enden muss. -
cornerRadius
Wir müssen diecornerRadius
Eigenschaft der Schaltfläche mit dem endgültigen Wert der Animation setzen, sonst wird der cornerRadius-Wert der Schaltfläche nach Abschluss der Animation automatisch auf den Anfangswert zurückgesetzt. -
addAnimation
Wir hängen das Animationsobjekt, das die Konfiguration des gesamten Animationsprozesses enthält, an die Ebene an, indem wir den Schlüsselpfad darstellen, für den die Animation ausgeführt werden muss. -
commit
Stellt das Ende des Animationscodeblocks dar und startet die Animation.
So würde die endgültige Animation aussehen:
Dieser Blog ist eine großartige Lektüre, um erweiterte Animationen zu erstellen, da er Sie übersichtlich durch die meisten APIs des Core Animation Frameworks führt und Sie durch jeden Schritt des Weges führt.
UIKitDynamics
UIKit Dynamics ist die Physik-Engine für UIKit, mit der Sie den UIKit-Steuerelementen beliebige physikalische Verhaltensweisen wie Kollision, Schwerkraft, Push, Snap usw. hinzufügen können.
UIKitDynamicAnimator
Dies ist die Admin-Klasse des UIKit Dynamics-Frameworks, die alle Animationen regelt, die von einem bestimmten UI-Steuerelement ausgelöst werden.
UIKitDynamicBehavior
Sie können einem Animator ein beliebiges physikalisches Verhalten hinzufügen, das ihn dann in der daran angehängten Ansicht ausführen kann.
Verschiedene Verhaltensweisen für UIKitDynamics umfassen:
UIAttachmentBehavior
UICollisionBehavior
UIFieldBehavior
UIGravityBehavior
UIPushBehavior
UISnapBehavior
Die Architektur von UIKitDynamics sieht ungefähr so aus. Beachten Sie, dass die Elemente 1 bis 5 durch eine einzelne Ansicht ersetzt werden können.
Lassen Sie uns ein physikalisches Verhalten auf unsere Schaltfläche anwenden. Wir werden sehen, wie man die Schwerkraft auf den Knopf anwendet, damit wir das Gefühl haben, mit einem realen Objekt umzugehen.
var dynamicAnimator : UIDynamicAnimator!var gravityBehavior : UIGravityBehavior!dynamicAnimator = UIDynamicAnimator(referenceView: self.view) //1gravityBehavior = UIGravityBehavior(items: ) //2dynamicAnimator.addBehavior(gravityBehavior) //3
Hier ist die Aufschlüsselung:
-
UIKitDynamicAnimator
Wir haben einUIKitDynamicAnimator
Objekt erstellt, das als Orchestrator für Animationen fungiert. Wir haben auch die Übersicht unserer Schaltfläche als Referenzansicht übergeben. -
UIGravityBehavior
Wir haben einUIGravityBehavior
Objekt erstellt und übergeben unseren Button an die Array-Elemente, auf die dieses Verhalten injiziert wird. -
addBehavior
Wir haben dem Animator das Gravity-Objekt hinzugefügt.
Dies sollte eine Animation erstellen, wie unten gezeigt:
Wir sollten dem Animator sagen, dass er den unteren Bildschirmrand als Boden betrachten soll. Hier kommt
UICollisionBehavior
ins Spiel.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
-
UICollisionBehavior
Wir haben einUICollisionBehavior
Objekt erstellt und die Schaltfläche übergeben, damit das Verhalten dem Element hinzugefügt wird. -
translatesReferenceBoundsIntoBoundary
Wenn Sie diese Eigenschaft aktivieren, wird der Animator angewiesen, die Grenze der Referenzansichten als Ende zu verwenden, in unserem Fall den unteren Bildschirmrand. -
addBehavior
Wir haben dem Animator hier ein Kollisionsverhalten hinzugefügt.
Nun sollte unser Knopf den Boden berühren und still stehen, wie unten gezeigt:
Das ist ziemlich ordentlich, nicht wahr?Lassen Sie uns nun versuchen, einen Bouncing-Effekt hinzuzufügen, damit sich unser Objekt realer anfühlt. Dazu verwenden wir die
UIDynamicItemBehavior
Klasse.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
-
UIDynamicItemBehavior
Wir haben einUIDynamicItemBehavior
Objekt erstellt und die Schaltfläche übergeben, damit das Verhalten dem Element hinzugefügt wird. -
elasticity
Der Wert muss zwischen 0-1 liegen, er stellt die Elastizität dar, d. H. Die Anzahl, wie oft das Objekt auf und vom Boden abprallen muss, wenn es getroffen wird. Hier passiert die Magie – indem Sie diese Eigenschaft optimieren, können Sie zwischen verschiedenen Arten von Objekten wie Bällen, Flaschen, harten Objekten usw. unterscheiden. -
addBehavior
Wir haben dem Animator hier ein Kollisionsverhalten hinzugefügt.
Jetzt sollte unser Button springen, wenn er auf den Boden trifft, wie unten gezeigt:
Dieses Repo ist sehr hilfreich und zeigt alle UIKitDynamics-Verhaltensweisen in Aktion. Es bietet auch Quellcode, um mit jedem Verhalten herumzuspielen. Das sollte meiner Meinung nach als eine umfangreiche Liste von Möglichkeiten dienen, iOS-Animationen für Ansichten auszuführen!
Im nächsten Abschnitt werfen wir einen kurzen Blick auf die Tools, die uns bei der Messung der Leistung von Animationen helfen. Ich würde Ihnen auch empfehlen, nach Möglichkeiten zu suchen, Ihren Xcode-Build zu optimieren, da dies eine große Menge Ihrer Entwicklungszeit spart.
Leistungsoptimierung
In diesem Abschnitt werden wir uns Möglichkeiten ansehen, die Leistung von iOS-Animationen zu messen und zu optimieren. Als iOS-Entwickler haben Sie möglicherweise bereits Xcode-Instrumente wie Speicherlecks und Zuweisungen verwendet, um die Leistung der gesamten App zu messen. Ebenso gibt es Instrumente, mit denen die Leistung von Animationen gemessen werden kann.
Core Animation
Instrument
Probieren Sie das Core Animation
Instrument aus und Sie sollten in der Lage sein, die FPS zu sehen, die Ihr App-Bildschirm liefert. Dies ist eine großartige Möglichkeit, die Leistung / Geschwindigkeit einer in Ihrer iOS-App gerenderten Animation zu messen.
Zeichnen
FPS wird in der App, die schwere Inhalte wie Bilder mit Effekten wie Schatten anzeigt, erheblich gesenkt. Versuchen Sie in solchen Fällen, das Bild mithilfe von Core Graphics-APIs separat in einem Kontext zu zeichnen, anstatt es direkt der image-Eigenschaft von UIImageView
zuzuweisen. Dies reduziert die Bildanzeigezeit übermäßig, indem die Bilddekomprimierungslogik asynchron ausgeführt wird, wenn sie in einem separaten Thread anstelle des Hauptthreads ausgeführt wird.
Rasterisierung
Rasterisierung ist ein Prozess, der verwendet wird, um komplexe Ebeneninformationen zwischenzuspeichern, so dass diese Ansichten nicht neu gezeichnet werden, wenn sie gerendert werden. Das Neuzeichnen von Ansichten ist die Hauptursache für die Reduzierung der FPS und daher ist es am besten, die Rasterung auf Ansichten anzuwenden, die mehrmals wiederverwendet werden.
Einpacken
Abschließend habe ich auch eine Liste nützlicher Ressourcen für iOS-Animationen zusammengefasst. Sie können dies sehr praktisch finden, wenn Sie an iOS-Animationen arbeiten. Darüber hinaus können Sie diese Design-Tools auch als (Design-) Schritt hilfreich finden, bevor Sie sich mit Animationen befassen.