Articles

Ausführen von iOS-Animationen auf Ansichten mit UIKit und UIView

  • 14 min lesen
  • Animation, iOS, UI, Mobile
  • Zum Offline-Lesen gespeichert
  • Teilen auf Twitter, LinkedIn
Dieser Artikel soll eine Einführung in iOS-Animationen geben, die verschiedene Möglichkeiten abdecken. Wir beginnen mit dem Verständnis der Grundlagen von Animationen, gehen zu den Kernframeworks über, erstellen ein einzelnes Beispiel mit den verschiedenen angebotenen Methoden und suchen schließlich nach Möglichkeiten, die Leistung zu optimieren.

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:

  1. 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.
  2. Wir setzen den neuen Frame der Schaltfläche, der den Endzustand der Animation darstellen soll.
  3. 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:

  1. duration
    Stellt die Dauer der Animation dar und bestimmt, wie lange der Codeblock ausgeführt werden soll.
  2. delay
    Stellt die anfängliche Verzögerung dar, die wir vor dem Start der Animation haben möchten.
  3. 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.
  4. velocity
    Stellt die Geschwindigkeit dar, mit der die Animation gestartet werden soll.
  5. options
    Art der Animationskurve, die Sie auf Ihre Ansichtsanimation anwenden möchten.
  6. 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:

  1. Wir rufen die UIViewProperty API auf, indem wir die Dauer und die Animationskurve übergeben.
  2. 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:

  1. duration
    Rufen Sie die API auf, indem Sie die Dauer der Animation übergeben.
  2. delay
    Anfängliche Verzögerungsdauer der Animation.
  3. options
    Die Art der Animationskurve, die Sie auf Ihre Ansichtsanimation anwenden möchten.
  4. animations
    Block, der alle vom Entwickler / Benutzer entworfenen Keyframe-Animationen aufnimmt.
  5. 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.
  6. relativeStartTime
    Definiert die Startzeit der Animation in der Sammlung des Animationsblocks.
  7. relativeDuration
    Definiert die Gesamtdauer dieser spezifischen Animation.
  8. 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:

  1. begin
    Stellt den Anfang des Animationscodeblocks dar.
  2. duration
    Gesamtdauer der Animation.
  3. curve
    Stellt die Zeitkurve dar, die auf die Animation angewendet werden muss.
  4. UIView.animate
    Unsere erste Animation, um den Rahmen der Schaltfläche zu ändern.
  5. CABasicAnimation
    Wir erstellen das CABasicAnimation -Objekt, indem wir die cornerRadius 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 Klasse CAKeyframeAnimation .
  6. fromValue
    Stellt den Startwert der Animation dar, d.h. den initialen cornerRadius Wert der Schaltfläche, von der aus die Animation beginnen muss.
  7. toValue
    Repräsentiert den endgültigen Wert der Animation, d.h. den endgültigen cornerRadius Wert der Schaltfläche, auf der die Animation enden muss.
  8. cornerRadius
    Wir müssen die cornerRadius 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.
  9. 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.
  10. 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:

  1. UIKitDynamicAnimator
    Wir haben ein UIKitDynamicAnimator Objekt erstellt, das als Orchestrator für Animationen fungiert. Wir haben auch die Übersicht unserer Schaltfläche als Referenzansicht übergeben.
  2. UIGravityBehavior
    Wir haben ein UIGravityBehavior Objekt erstellt und übergeben unseren Button an die Array-Elemente, auf die dieses Verhalten injiziert wird.
  3. addBehavior
    Wir haben dem Animator das Gravity-Objekt hinzugefügt.
    Dies sollte eine Animation erstellen, wie unten gezeigt:
    Beachten Sie, wie die Schaltfläche von der Mitte (ihrer ursprünglichen Position) des Bildschirms nach unten und darüber hinaus abfällt.

    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
  4. UICollisionBehavior
    Wir haben ein UICollisionBehavior Objekt erstellt und die Schaltfläche übergeben, damit das Verhalten dem Element hinzugefügt wird.
  5. translatesReferenceBoundsIntoBoundary
    Wenn Sie diese Eigenschaft aktivieren, wird der Animator angewiesen, die Grenze der Referenzansichten als Ende zu verwenden, in unserem Fall den unteren Bildschirmrand.
  6. 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
  7. UIDynamicItemBehavior
    Wir haben ein UIDynamicItemBehavior Objekt erstellt und die Schaltfläche übergeben, damit das Verhalten dem Element hinzugefügt wird.
  8. 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.
  9. 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.