Articles

Wykonywanie animacji iOS na widokach z UIKit i UIView

  • 14 min Czytaj
  • Animacja,iOS,UI,Mobile
  • zapisane do czytania offline
  • Udostępnij na Twitterze, LinkedIn
ten artykuł ma być podkład na animacje iOS wyczerpująco obejmujące różne sposoby robienia tego. Zaczynamy od zrozumienia podstaw animacji, przejdziemy do podstawowych frameworków, budując jeden przykład przy użyciu różnych oferowanych metod, a na koniec przyglądamy się sposobom dostrojenia wydajności.

jestem programistą iOS od ponad dekady i rzadko widziałem artykuły, które konsolidują wszystkie możliwe sposoby wykonywania animacji w iOS. Ten artykuł ma być podstawą animacji iOS z zamiarem wyczerpującego omówienia różnych sposobów robienia tego samego.

biorąc pod uwagę obszerność tematu, omówilibyśmy każdą część zwięźle na dość wysokim poziomie. Celem jest edukowanie czytelnika z zestawem opcji dodawania animacji do jego aplikacji na iOS.

zanim zaczniemy od tematów związanych z iOS, rzućmy okiem na szybkość animacji.

animowanie z prędkością 60 klatek na sekundę

zazwyczaj w filmach każda klatka jest reprezentowana przez obraz, a liczba klatek na sekundę określa liczbę obrazów odwróconych w sekwencji. Jest to określane jako „klatek na sekundę” lub FPS.

FPS określa liczbę zdjęć przerzuconych w ciągu sekundy, co dosłownie oznacza, że im więcej zdjęć/ klatek, tym więcej szczegółów / informacji jest wyświetlanych w filmie. Dotyczy to również animacji.

FPS jest zwykle używany do określania jakości animacji. Istnieje popularna opinia, że każda dobra animacja powinna działać z prędkością 60 klatek na sekundę lub wyższą — wszystko mniej niż 60 klatek na sekundę byłoby nieco wyłączone.

chcesz zobaczyć różnicę między 30FPS a 60FPS? Sprawdź to!

zauważyłeś różnicę? Ludzkie oczy mogą zdecydowanie czuć jitter przy niższych fps. Dlatego zawsze dobrą praktyką jest upewnienie się, że każda tworzona animacja jest zgodna z podstawową zasadą działania z prędkością 60 klatek na sekundę lub wyższą. To sprawia, że czuje się bardziej realistyczny i żywy.

po przyjrzeniu się FPS, przejdźmy teraz do różnych podstawowych frameworków iOS, które zapewniają nam sposób na wykonywanie animacji.

podstawowe frameworki

w tej sekcji omówimy frameworki w iOS SDK, które mogą być używane do tworzenia animacji widoku. Przeprowadzimy krótki spacer po każdym z nich, wyjaśniając ich zestaw funkcji za pomocą odpowiedniego przykładu.

animacje UIKit/UIView

UIView jest klasą bazową dla dowolnego widoku, który wyświetla zawartość w aplikacjach iOS.

UIKit, framework, który daje nam UIView, zapewnia nam już kilka podstawowych funkcji animacji, które sprawiają, że programiści mogą osiągnąć więcej, robiąc mniej.

API, UIView.animate, jest najprostszym sposobem animowania widoków, ponieważ właściwości każdego widoku można łatwo animować, podając wartości właściwości w składni opartej na blokach.

w animacjach UIKit zaleca się modyfikowanie tylko animowanych właściwości UIVIew w przeciwnym razie pojawią się reperkusje, w których animacje mogą spowodować nieoczekiwany stan widoku.

animacja(withDuration: animations: completion)

ta metoda przyjmuje czas trwania animacji, zestaw animowanych zmian właściwości widoku, które muszą być animowane. Blok dopełnienia daje wywołanie zwrotne, gdy widok jest zakończony z wykonaniem animacji.

prawie każdy rodzaj animacji, jak poruszanie się, skalowanie, obracanie, blaknięcie itp. w widoku można osiągnąć za pomocą tego pojedynczego API.

teraz rozważ, że chcesz animować zmianę rozmiaru przycisku lub chcesz, aby określony widok powiększył ekran. W ten sposób możemy to zrobić za pomocą UIView.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}

oto co tutaj robimy:

  1. nazywamy metodęUIView.animate z przekazaną do niej wartością czasu trwania, która określa jak długo animacja opisana wewnątrz bloku powinna działać.
  2. ustawiamy nową klatkę przycisku, która powinna reprezentować końcowy stan animacji.
  3. ustawiamy przycisk center z jego centrum tak, aby pozostał na środku ekranu.

powyższy blok kodu animacji powinien wywołać animację klatki przycisku zmieniającej się z bieżącej klatki:

Width = 0, Height = 0

do ostatniej klatki:

Width = Height = newButtonWidth

a oto jak wyglądałaby animacja:

animateWithDuration

ta metoda jest rozszerzeniem metody animate, gdzie można zrobić wszystko, co można wykonać w poprzednim API, z pewnymi zachowaniami fizyki dodanymi do animacji widoku.

na przykład, jeśli chcesz uzyskać efekty tłumienia sprężyn w animacji, którą zrobiliśmy powyżej, to tak wyglądałby Kod:

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)

oto zestaw parametrów, których używamy:

  1. duration
    reprezentuje czas trwania animacji określający, jak długo powinien działać blok kodu.
  2. reprezentuje początkowe opóźnienie, które chcemy mieć przed rozpoczęciem animacji.
  3. SpringWithDamping
    reprezentuje wartość efektu sprężystości, który ma zachowywać się w widoku. Wartość musi zawierać się w przedziale od 0 do 1. Im niższa wartość, tym wyższe oscylacje sprężyny.
  4. velocity
    reprezentuje szybkość, z jaką animacja powinna się rozpocząć.
  5. options
    rodzaj krzywej animacji, którą chcesz zastosować do swojej animacji widoku.
  6. wreszcie blok kodu, w którym ustawiamy ramkę przycisku, który ma być animowany. Jest taki sam jak poprzednia animacja.

A oto jak wyglądałaby animacja z powyższą konfiguracją animacji:

UIViewPropertyAnimator

aby uzyskać nieco większą kontrolę nad animacjami,UIViewPropertyAnimator jest przydatny, gdy zapewnia nam sposób na wstrzymanie i wznowienie animacji. Możesz mieć niestandardowy czas i mieć animację interaktywną i przerywalną. Jest to bardzo pomocne podczas wykonywania animacji, które są również interaktywne z działaniami użytkownika.

klasyczny gest „Przesuń, aby odblokować” i widok odtwarzacza Odrzuć/ rozwiń animację (w aplikacji Muzyka) to przykłady interaktywnych i przerywanych animacji. Możesz rozpocząć przesuwanie widoku palcem, a następnie zwolnić go, a Widok powróci do pierwotnej pozycji. Możesz również uchwycić widok podczas animacji i kontynuować przeciąganie go palcem.

poniżej znajduje się prosty przykład tego, jak możemy uzyskać animację za pomocą 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

oto, co robimy:

  1. nazywamy UIViewProperty API przekazując czas trwania i krzywą animacji.
  2. w przeciwieństwie do obu powyższych UIView.animate API, animacja nie uruchomi się, jeśli nie określisz jej samodzielnie, tzn. masz pełną kontrolę nad całym procesem/ przepływem animacji.

teraz powiedzmy, że chcesz mieć jeszcze większą kontrolę nad animacjami. Na przykład chcesz zaprojektować i kontrolować każdą klatkę w animacji. Jest do tego jeszcze inne API ,animateKeyframes. Ale zanim zagłębimy się w to, przyjrzyjmy się szybko, czym jest Klatka w animacji.

Co To jest frame?

zbiór zmian/przejść klatki widoku, od stanu początkowego do stanu końcowego, jest zdefiniowany jakoanimation, a każda pozycja widoku podczas animacji jest wywoływana jakoframe.

animateKeyframes

To API zapewnia sposób projektowania animacji w taki sposób, że można zdefiniować wiele animacji z różnymi czasami i przejściami. Po tym, API po prostu integruje wszystkie animacje w jednym bezproblemowym doświadczeniu.

powiedzmy, że chcemy przesunąć nasz przycisk na ekranie w losowy sposób. Zobaczmy, jak możemy użyć do tego interfejsu API animacji klatek kluczowych.

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 }})

oto podział:

  1. duration
    wywołanie API poprzez podanie czasu trwania animacji.
  2. początkowy czas opóźnienia animacji.
  3. options
    typ krzywej animacji, którą chcesz zastosować do swojej animacji widoku.
  4. animations
    blok, który pobiera wszystkie animacje klatek kluczowych zaprojektowane przez programistę / użytkownika.
  5. addKeyFrame
    wywołaj API do projektowania każdej animacji. W naszym przypadku zdefiniowaliśmy każdy ruch przycisku. Możemy mieć tyle takich animacji, ile potrzebujemy, dodanych do bloku.
  6. relativeStartTime
    określa czas rozpoczęcia animacji w zbiorze bloku animacji.
  7. relativeDuration
    określa całkowity czas trwania tej konkretnej animacji.
  8. center
    w naszym przypadku wystarczy zmienić właściwość center przycisku, aby przesunąć przycisk po ekranie.

i tak wyglądają animacje końcowe:

CoreAnimation

każda animacja oparta na UIKit jest wewnętrznie tłumaczona na animacje podstawowe. W ten sposób Rdzeń animacji działa jako warstwa podkładowa lub szkielet dla każdej animacji UIKit. W związku z tym wszystkie interfejsy API animacji UIKit są tylko zamkniętymi warstwami podstawowych interfejsów API animacji w łatwy w użyciu lub wygodny sposób.

interfejsy API animacji UIKit nie zapewniają dużej kontroli nad animacjami, które zostały wykonane w widoku, ponieważ są one używane głównie do animowania właściwości widoku. Dlatego w takich przypadkach, w których chcesz mieć kontrolę nad każdą klatką animacji, lepiej jest bezpośrednio użyć podstawowych interfejsów API animacji. Alternatywnie, zarówno animacje UIView, jak i animacje core mogą być używane w połączeniu.

UIView + Core Animation

zobaczmy, jak możemy odtworzyć ten sam przycisk Zmień animację wraz z określeniem krzywej czasowej za pomocą interfejsów API UIView i Core Animation.

możemy użyćCATransaction funkcji taktowania, które pozwalają określić i kontrolować krzywą animacji.

przyjrzyjmy się przykładowi animacji zmiany rozmiaru przycisku z promieniem rogu wykorzystującej funkcjęCATransactionI kombinację animacji UIView:

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

oto podział:

  1. begin
    reprezentuje początek bloku kodu animacji.
  2. duration
    ogólny czas trwania animacji.
  3. curve
    reprezentuje krzywą czasu, która musi być zastosowana do animacji.
  4. UIView.animate
    Nasza pierwsza Animacja do zmiany klatki przycisku.
  5. CABasicAnimation
    tworzymy obiektCABasicAnimation odwołując się docornerRadius przycisku jako ścieżki klawiatury, ponieważ to chcemy animować. Podobnie, jeśli chcesz mieć szczegółową kontrolę nad animacjami klatek kluczowych, możesz użyć klasyCAKeyframeAnimation.
  6. fromValue
    przedstawia wartość początkową animacji, tzn. początkowącornerRadius wartość przycisku, od którego animacja ma się rozpocząć.
  7. toValue
    przedstawia ostateczną wartość animacji, tzn. ostatecznącornerRadius wartość przycisku, na którym animacja ma się zakończyć.
  8. cornerRadius
    musimy ustawićcornerRadius właściwość przycisku z końcową wartością animacji w przeciwnym razie wartość cornerRadius przycisku zostanie automatycznie przywrócona do wartości początkowej po zakończeniu animacji.
  9. addAnimation
    do warstwy dołączamy obiekt animacji, który zawiera konfigurację całego procesu animacji, reprezentując ścieżkę klawiatury, dla której animacja ma być wykonana.
  10. commit
    reprezentuje koniec bloku kodu animacji i rozpoczyna animację.

tak wyglądałaby ostateczna animacja:

Ten blog to świetna lektura, która pomaga tworzyć bardziej zaawansowane animacje, ponieważ dokładnie prowadzi cię przez większość podstawowych interfejsów API struktury animacji z instrukcjami prowadzi cię przez każdy krok.

UIKitDynamics

UIKit Dynamics to silnik fizyki dla UIKit, który umożliwia dodawanie do kontrolek UIKit dowolnych zachowań fizycznych, takich jak kolizja, grawitacja, pchanie, przyciąganie itp.

UIKitDynamicAnimator

jest to klasa administracyjna frameworka UIKit Dynamics, która reguluje wszystkie animacje wyzwalane przez dowolną kontrolę interfejsu użytkownika.

UIKitDynamicBehavior

umożliwia dodanie dowolnego zachowania fizycznego do animatora, który następnie umożliwia jego wykonanie na załączonym do niego widoku.

różne rodzaje zachowań dla UIKitDynamics obejmują:

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

architektura uikitdynamics wygląda mniej więcej tak. Należy pamiętać, że pozycje od 1 do 5 można zastąpić pojedynczym widokiem.

zastosujmy trochę fizyki do naszego przycisku. Zobaczymy, jak zastosować grawitację do przycisku, aby dało nam to poczucie radzenia sobie z prawdziwym obiektem.

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

oto podział:

  1. UIKitDynamicAnimator
    stworzyliśmy obiektUIKitDynamicAnimator, który pełni funkcję orchestratora do wykonywania animacji. Przekazaliśmy również podgląd naszego przycisku jako widok referencyjny.
  2. UIGravityBehavior
    utworzyliśmyUIGravityBehavior obiekt i przekazujemy nasz przycisk do elementów tablicy, na których to zachowanie jest wstrzykiwane.
  3. addBehavior
    dodaliśmy obiekt grawitacyjny do animatora.
    to powinno stworzyć animację, jak pokazano poniżej:
    zwróć uwagę, jak przycisk spada od środka (jego pierwotnej pozycji) ekranu do dołu i dalej.

    powinniśmy powiedzieć animatorowi, aby uważał dno ekranu za podłoże. Tutaj pojawia sięUICollisionBehavior.

    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
    stworzyliśmy obiektUICollisionBehavior I przekazaliśmy go wzdłuż przycisku, tak aby zachowanie zostało dodane do elementu.
  5. translatesReferenceBoundsIntoBoundary
    włączenie tej właściwości mówi animatorowi, aby wziął granicę widoków odniesienia jako koniec, który w naszym przypadku jest dolną częścią ekranu.
  6. addBehavior
    dodaliśmy zachowanie kolizji do animatora tutaj.
    Teraz nasz przycisk powinien uderzyć w ziemię i stać nieruchomo, jak pokazano poniżej:

    to całkiem niezłe, prawda?
    spróbujmy teraz dodać efekt odbijania się, aby nasz obiekt czuł się bardziej realny. W tym celu użyjemy klasy UIDynamicItemBehavior.

    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
    stworzyliśmyUIDynamicItemBehavior obiekt i przekazujemy wzdłuż przycisku tak, aby zachowanie zostało dodane do elementu.
  8. elasticity
    wartość musi zawierać się w przedziale 0-1, oznacza to elastyczność, tzn. ilość razy obiekt musi odbijać się od ziemi i od niej w momencie uderzenia. Tutaj dzieje się magia – poprawiając tę właściwość, możesz odróżnić różne rodzaje przedmiotów, takich jak kulki, butelki, twarde przedmioty i tak dalej.
  9. addBehavior
    dodaliśmy zachowanie kolizji do animatora tutaj.

teraz nasz przycisk powinien odbić się, gdy uderzy w ziemię, jak pokazano poniżej:

Ten repo jest bardzo pomocny i pokazuje wszystkie zachowania UIKitDynamics w akcji. Zapewnia również kod źródłowy do zabawy z każdym zachowaniem. To, moim zdaniem, powinno służyć jako obszerna lista sposobów wykonywania animacji iOS na widokach!

w następnej sekcji przyjrzymy się krótko narzędziom, które pomogą nam w pomiarze wydajności animacji. Polecam również, aby spojrzeć na sposoby optymalizacji kompilacji Xcode, ponieważ pozwoli to zaoszczędzić ogromną ilość czasu rozwoju.

dostrajanie wydajności

w tej sekcji przyjrzymy się sposobom pomiaru i dostrojenia wydajności animacji iOS. Jako programista iOS mogłeś już używać instrumentów Xcode, takich jak wycieki pamięci i alokacje do pomiaru wydajności całej aplikacji. Podobnie, istnieją instrumenty, które mogą być używane do pomiaru wydajności animacji.

Core Animation Instrument

spróbujCore Animation instrument, a powinieneś zobaczyć FPS, które dostarcza ekran aplikacji. Jest to świetny sposób, aby zmierzyć wydajność/ szybkość dowolnej animacji renderowanej w aplikacji na iOS.

rysowanie

FPS jest znacznie obniżone w aplikacji, która wyświetla ciężkie treści, takie jak obrazy z efektami takimi jak cienie. W takich przypadkach zamiast przypisywać obraz bezpośrednio do właściwości obrazu UIImageView, spróbuj narysować obraz oddzielnie w kontekście przy użyciu podstawowych interfejsów API Grafiki. To nadmiernie skraca czas wyświetlania obrazu, wykonując logikę dekompresji obrazu asynchronicznie, gdy odbywa się to w oddzielnym wątku zamiast głównego wątku.

Rasteryzacja

Rasteryzacja jest procesem używanym do buforowania złożonych informacji o warstwie, dzięki czemu widoki te nie są przerysowywane podczas renderowania. Przerysowanie widoków jest główną przyczyną zmniejszenia liczby klatek na sekundę i dlatego najlepiej jest zastosować rasteryzację na widokach, które mają być ponownie użyte kilka razy.

Podsumowując

podsumowując, podsumowałem również listę przydatnych zasobów dla animacji iOS. Może się to okazać przydatne podczas pracy z animacjami iOS. Ponadto ten zestaw narzędzi do projektowania może być pomocny jako krok (projekt) przed zagłębianiem się w animacje.