Upgrade to Pro — share decks privately, control downloads, hide ads and more …

UIViewPropertyAnimatorで実現するリッチなアニメーション表現

03c0e11ea6f2a3e08b3c46db5877c8e1?s=47 Jiro Nagashima
September 02, 2018

 UIViewPropertyAnimatorで実現するリッチなアニメーション表現

iOSDC 2018 9/2 14:40~ Track D で登壇した内容です

https://fortee.jp/iosdc-japan-2018/proposal/5a1a99cb-9b59-4d94-a655-49ffe3e7b91b

03c0e11ea6f2a3e08b3c46db5877c8e1?s=128

Jiro Nagashima

September 02, 2018
Tweet

Transcript

  1. ©2018 Wantedly, Inc. 2018.9.2 - UIViewPropertyAnimator Ͱ ࣮ݱ͢ΔϦονͳΞχϝʔγϣϯදݱ iOSDC 2018

    Jiro @hedjirog
  2. ©2018 Wantedly, Inc. Jiro Wantedly, Inc. / Engineer ΤϯδχΞɻελʔτΞοϓͷॳظ։ൃɺສϢʔβʔΛ๊͑ΔΞϓϦͷ ಺੡Խɺάϩʔεظʹ͓͚Δࢪࡦ࣮ࢪͳͲɺJ04ΞϓϦ։ൃΛத৺ʹ༷ʑͳ

    ։ൃϑΣʔζΛܦݧɻϑϦʔϥϯεظʹܞΘͬͨWantedlyͰάϩʔενʔ ϜΛϦʔυ͢Δཱ৔ͱͯ͠౓໨ͷ௅ઓʂ Twitter: @hedjirog
  3. ©2018 Wantedly, Inc. αϯϓϧίʔυ

  4. ©2018 Wantedly, Inc. https://github.com /hedjirog/CustomPresentation

  5. ©2018 Wantedly, Inc. αϯϓϧίʔυ ը໘ભҠͷΞχϝʔγϣϯΛ࣮૷ w ෳ਺ͷUIViewPropertyAnimatorΛ࿈ಈ w WWDC 2017

    Session 230 “Advanced Animations with UIKit” Ͱఏࣔ͞Εͨख๏ w ख๏ͷվྑΛՃ࣮͑૷Λࢼͨ͠΋ͷ https://github.com /hedjirog/CustomPresentation
  6. ©2018 Wantedly, Inc. Demo

  7. ©2018 Wantedly, Inc.

  8. ©2018 Wantedly, Inc. 1 3 6 4 5 2

  9. ©2018 Wantedly, Inc. 1 3 6 4 5 2 ෳ਺ͷUIViewPropertyAnimator

    ͕࿈ಈ  γʔτͱϥϕϧͷҠಈ ֦େॖখ   γʔτͷؙ֯  ϥϕϧͷೱ୶  ϥϕϧͷೱ୶  Ϙλϯͷೱ୶  എܠͷೱ୶
  10. ©2018 Wantedly, Inc. UIViewPropertyAnimatorͷ֓ཁ

  11. ©2018 Wantedly, Inc. Ξχϝʔγϣϯ࣮૷ͷͨΊͷΫϥε w Ξχϝʔγϣϯͷऴྃ·Ͱʹಈ࡞Λಈతʹมߋ͢Δ͜ͱ͕Ͱ͖Δ w ϓϩύςΟͷ஋ w ΞχϝʔγϣϯΧʔϒ

    w ਐߦ౓߹͍ w ਐߦํ޲ w ΠϯλϥΫςΟϒͳΞχϝʔγϣϯʹస׵Մೳ UIViewPropertyAnimator
  12. ©2018 Wantedly, Inc. ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI

  13. ©2018 Wantedly, Inc. UIViewControllerTransitioningDelegate w 3ͭͷ DPOUSPMMFS Λܾఆ͢ΔϝιουΛ࣋ͭϓϩτίϧ • Presentation

    Controller • Animation Controller • Interaction Controller w ભҠઌͷ view controller ͷ transitioningDelegate ϓϩύςΟʹઃఆ ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI
  14. ©2018 Wantedly, Inc. UIViewController TransitioningDelegate Presentation Controller Animation Controller Interaction

    Controller Protocol
  15. ©2018 Wantedly, Inc. UIPresentationController w ભҠݩͱભҠઌͷview controllerͷදࣔΛ؅ཧ͢ΔΫϥε w ΧελϜͷϏϡʔΛࠩ͠ࠐΉ͜ͱ͕Ͱ͖Δ ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI

  16. ©2018 Wantedly, Inc. UIViewController TransitioningDelegate Presentation Controller Animation Controller Interaction

    Controller UIPresentationController Protocol Class
  17. ©2018 Wantedly, Inc. UIViewControllerAnimatedTransitioning w ભҠͷΞχϝʔγϣϯΛܾఆ͢ΔϝιουΛ࣋ͭϓϩτίϧ w ϓϩτίϧʹ४ڌͨ͠ animation controller

    Λఆٛɺtransitioning delegateͰฦ٫ w ભҠઌͷview controllerͷදࣔɾඇදࣔͦΕͧΕͷBOJNBUJPO controllerΛࢦఆՄೳ ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI
  18. ©2018 Wantedly, Inc. UIViewController TransitioningDelegate Presentation Controller Animation Controller Interaction

    Controller UIViewController AnimatedTransitioning UIPresentationController Protocol Class
  19. ©2018 Wantedly, Inc. UIViewControllerInteractiveTransitioning w ΞχϝʔγϣϯͷΠϯλϥΫςΟϒʹ͢Δࡍʹར༻͞ΕΔ w ϓϩτίϧʹ४ڌͨ͠ interaction controller

    Λఆٛɺtransitioning delegateͰฦ٫ w ϓϩτίϧʹ४ڌͨ͠UIPercentDrivenInteractiveTransitionΫϥε͕ఏڙ͞Ε͍ͯΔ w ભҠઌͷview controllerͷදࣔɾඇදࣔͦΕͧΕͷJOUFSBDUJPO controllerΛࢦఆՄೳ ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI
  20. ©2018 Wantedly, Inc. UIViewController TransitioningDelegate Presentation Controller Animation Controller Interaction

    Controller UIViewController AnimatedTransitioning UIPresentationController UIPercentDrivenInteractiveTransition UIViewController InteractiveTransitioning Protocol Class
  21. ©2018 Wantedly, Inc. αϯϓϧίʔυͷ࣮૷

  22. ©2018 Wantedly, Inc. present dismiss ભҠૢ࡞ͷఆٛ

  23. ©2018 Wantedly, Inc. ભҠૢ࡞ͷఆٛ enum PresentationOperation { case present case

    dismiss var duration: TimeInterval { return 0.6 } }
  24. ©2018 Wantedly, Inc. PresentationController ͷ࣮૷ ੹຿Λҙࣝͨ͠Ϋϥεͷ෼ׂ

  25. ©2018 Wantedly, Inc. Ϋϥεͷ෼ׂ

  26. ©2018 Wantedly, Inc. جຊͷ3ͭͷΫϥε 1. PresentationController • UIPresentationController ͷαϒΫϥε •

    ભҠݩͱભҠઌͷը໘ؒʹΧελϜͷϏϡʔΛࠩ͠ࠐΉ 2. PresentationAnimationController • UIViewControllerAnimatedTransitioning ʹ४ڌ • ΞχϝʔγϣϯΛू໿ͤͯ͞ભҠΞχϝʔγϣϯΛఆٛ͢Δ 3. PresentationInteractionController • UIPercentDrivenInteractiveTransition ͷαϒΫϥε • δΣενϟΛײ஌ͯ͠ΞχϝʔγϣϯͷਐߦΛ੍ޚ͢Δ Ϋϥεͷ෼ׂ PresentationController (UIPresentationController) PresentationAnimationController PresentationInteractionController (UIPercentDrivenInteractiveTransition)
  27. ©2018 Wantedly, Inc. UIViewController TransitioningDelegate PresentationController (UIPresentationController) PresentationInteractionController (UIPercentDrivenInteractiveTransition )

    UIViewController InteractiveTransitioning Protocol Class PresentationAnimationController UIViewController AnimatedTransitioning
  28. ©2018 Wantedly, Inc. Ξχϝʔγϣϯͷఆٛ

  29. ©2018 Wantedly, Inc. Ξχϝʔγϣϯͷఆٛ Wiew Λอ࣋͢Δ controller ͰఆٛՄೳʹ͢Δ w Ξχϝʔγϣϯͷఆٛʹ͸WJFXͷࢀর͕ඞཁ

    w action controller͕ભҠݩ΍ભҠઌͷviewͷߏ଄Λ஌Βͳͯ͘΋ྑ͍Α͏ʹ͍ͨ͠ w Ξχϝʔγϣϯ͸controllerͰఆٛΛͯ͠ϓϩτίϧΛհͯ͠ू໿Մೳʹ͢Δ Presentation AnimatedTransitioning
  30. ©2018 Wantedly, Inc. UIViewController TransitioningDelegate PresentationController (UIPresentationController) PresentationInteractionController (UIPercentDrivenInteractiveTransition )

    UIViewController InteractiveTransitioning Protocol Class PresentationAnimationController UIViewController AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning
  31. ©2018 Wantedly, Inc. protocol PresentationAnimatedTransitioning { func prepareForTransition(using operation: PresentationOperation)

    func transitionAnimators(operation: PresentationOperation, duration: TimeInterval) -> [UIViewPropertyAnimator] } Ξχϝʔγϣϯͷఆٛ Presentation AnimatedTransitioning
  32. ©2018 Wantedly, Inc. δΣενϟͷఆٛ

  33. ©2018 Wantedly, Inc. δΣενϟͷఆٛ Wiew Λอ࣋͢Δ controller ͰఆٛՄೳʹ͢Δ w δΣενϟʔͷఆٛʹ͸WJFXͷࢀর͕ඞཁ

    w interaction controller͕ભҠݩ΍ભҠઌͷviewͷߏ଄Λ஌Βͳͯ͘΋ྑ͍Α͏ʹ͍ͨ͠ w δΣενϟʔ͸controllerͰఆٛΛͯ͠ϓϩτίϧΛհͯ͠ू໿Մೳʹ͢Δ Presentation InteractiveTransitioning
  34. ©2018 Wantedly, Inc. UIViewController TransitioningDelegate PresentationController (UIPresentationController) PresentationInteractionController (UIPercentDrivenInteractiveTransition )

    UIViewController InteractiveTransitioning Protocol Class PresentationAnimationController UIViewController AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation InteractiveTransitioning Presentation InteractiveTransitioning
  35. ©2018 Wantedly, Inc. protocol PresentationInteractiveTransitioning { var interactivePanGestureRecognizer: UIPanGestureRecognizer {

    get } } Ξχϝʔγϣϯͷఆٛ Presentation InteractiveTransitioning
  36. ©2018 Wantedly, Inc. ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ

  37. ©2018 Wantedly, Inc. ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ PresentationController ͷΠχγϟϥΠβΛ޻෉͢Δ w ΠχγϟϥΠβҾ਺ͷܕΛϓϩτίϧʹ४ڌ͢Δ͜ͱΛཁٻ͢ΔΑ͏ʹ͢Δ w PresentationControllerࣗ਎ΛભҠσϦήʔτʹ͢Δ

    w UIViewControllerTransitioningDelegate ʹ४ڌͤ͞Δ PresentationController (UIPresentationController) UIViewController TransitioningDelegate
  38. ©2018 Wantedly, Inc. PresentationInteractionController (UIPercentDrivenInteractiveTransition ) UIViewController InteractiveTransitioning Protocol Class

    PresentationAnimationController UIViewController AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation InteractiveTransitioning Presentation InteractiveTransitioning UIViewController TransitioningDelegate Presentation AnimatedTransitioning PresentationController (UIPresentationController)
  39. ©2018 Wantedly, Inc. typealias PresentableViewController = UIViewController & PresentationAnimatedTransitioning &

    PresentationInteractiveTransitioning class PresentationController: UIPresentationController { init(presentedViewController: PresentableViewController, presentingViewController: PresentableViewController) { super.init(presentedViewController: presentedViewController, presenting: presentingViewController) presentedViewController.modalPresentationStyle = .custom } ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ PresentationController (UIPresentationController) UIViewController TransitioningDelegate
  40. ©2018 Wantedly, Inc. extension PresentationController: UIViewControllerTransitioningDelegate { func presentationController(forPresented presented:

    UIViewController, presenting: UIViewController?, source: UIViewController ) -> UIPresentationController? { return self } func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController ) -> UIViewControllerAnimatedTransitioning? { return PresentationAnimationController(operation: .present) } func animationController(forDismissed dismissed: UIViewController ) -> UIViewControllerAnimatedTransitioning? { return PresentationAnimationController(operation: .dismiss) } } ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ PresentationController (UIPresentationController) UIViewController TransitioningDelegate
  41. ©2018 Wantedly, Inc. private func presentSecondViewController() { let presentationController =

    PresentationController(presentedViewController: secondViewController, presentingViewController: self) secondViewController.transitioningDelegate = presentationController present(secondViewController, animated: true) } ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ PresentationController (UIPresentationController) UIViewController TransitioningDelegate
  42. ©2018 Wantedly, Inc. AnimationController ͷ࣮૷ ෳ਺ͷΞχϝʔγϣϯΛ࿈ಈͤ͞Δ

  43. ©2018 Wantedly, Inc. Ξχϝʔγϣϯͷ࣮૷

  44. ©2018 Wantedly, Inc. extension PresentationController: PresentationAnimatedTransitioning { func transitionAnimators(operation: PresentationOperation,

    duration: TimeInterval) -> [UIViewPropertyAnimator] { let curve: UIViewAnimationCurve = operation == .present ? .easeIn : .easeOut let dimmingAnimator = UIViewPropertyAnimator(duration: duration, curve: curve) { self.dimmingView.alpha = self.dimmingViewAlpha(for: operation) } return [dimmingAnimator] } private func dimmingViewAlpha(for operation: PresentationOperation) -> CGFloat { return operation == .present ? 0.2 : 0 } } Ξχϝʔγϣϯͷ࣮૷ Presentation AnimatedTransitioning PresentationController (UIPresentationController)
  45. ©2018 Wantedly, Inc. Ξχϝʔγϣϯͷू໿

  46. ©2018 Wantedly, Inc. UIViewController TransitioningDelegate PresentationInteractionController (UIPercentDrivenInteractiveTransition ) UIViewController InteractiveTransitioning

    Protocol Class PresentationAnimationController UIViewController AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation InteractiveTransitioning Presentation InteractiveTransitioning Presentation AnimatedTransitioning PresentationController (UIPresentationController)
  47. ©2018 Wantedly, Inc. PresentationInteractionController (UIPercentDrivenInteractiveTransition ) UIViewController InteractiveTransitioning Protocol Class

    PresentationAnimationController UIViewController AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation InteractiveTransitioning Presentation InteractiveTransitioning 1 3 4 5 2 UIViewController TransitioningDelegate Presentation AnimatedTransitioning 6 PresentationController (UIPresentationController)
  48. ©2018 Wantedly, Inc. PresentationInteractionController (UIPercentDrivenInteractiveTransition ) UIViewController InteractiveTransitioning Protocol Class

    PresentationAnimationController UIViewController AnimatedTransitioning Presentation AnimatedTransitioning Presentation AnimatedTransitioning Presentation InteractiveTransitioning Presentation InteractiveTransitioning UIViewController TransitioningDelegate 1 3 6 4 5 2 Presentation AnimatedTransitioning PresentationController (UIPresentationController)
  49. ©2018 Wantedly, Inc. class PresentationAnimationController: NSObject, UIViewControllerAnimatedTransitioning { private var

    transitionAnimator: CoordinatedAnimator? func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning ) -> UIViewImplicitlyAnimating { if let transitionAnimator = transitionAnimator { return transitionAnimator } let duration = transitionDuration(using: transitionContext) var animators: [UIViewPropertyAnimator] = [] [fromViewController, toViewController, presentationController].forEach { animators += $0.transitionAnimators(operation: operation, duration: duration) } … Ξχϝʔγϣϯͷू໿ PresentationAnimationController UIViewController AnimatedTransitioning 1 3 6 4 5 2
  50. ©2018 Wantedly, Inc. ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ

  51. ©2018 Wantedly, Inc. class PresentationAnimationController: NSObject, UIViewControllerAnimatedTransitioning { private var

    transitionAnimator: CoordinatedAnimator? func interruptibleAnimator(using transitionContext: UIViewControllerContextTransitioning ) -> UIViewImplicitlyAnimating { if let transitionAnimator = transitionAnimator { return transitionAnimator } let duration = transitionDuration(using: transitionContext) var animators: [UIViewPropertyAnimator] = [] [fromViewController, toViewController, presentationController].forEach { animators += $0.transitionAnimators(operation: operation, duration: duration) } … ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ PresentationAnimationController UIViewController AnimatedTransitioning 1 3 6 4 5 2
  52. ©2018 Wantedly, Inc. ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ UIViewImplicitlyAnimating ʹ४ڌͨ͠Ξχϝʔγϣϯ͕ඞཁ w ΧελϜͷΞχϝʔγϣϯΛఆٛ w ෳ਺ͷUIViewPropertyAnimatorΛΠχγϟϥΠβҾ਺Ͱड͚औΔ

    w Ξχϝʔγϣϯͷ੍ޚ໋ྩʹैͬͯू໿ͨ͠ΞχϝʔγϣϯΛ࿈ಈͤͯ͞ಈ͔͢ PresentationAnimationController UIViewController AnimatedTransitioning 1 3 6 4 5 2
  53. ©2018 Wantedly, Inc. class CoordinatedAnimator: NSObject, UIViewImplicitlyAnimating { private let

    primaryAnimator: UIViewPropertyAnimator private var animators: [UIViewPropertyAnimator] init(primaryAnimator: UIViewPropertyAnimator, secondaryAnimators: [UIViewPropertyAnimator]) { self.primaryAnimator = primaryAnimator self.animators = [primaryAnimator] + secondaryAnimators } … ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ PresentationAnimationController UIViewController AnimatedTransitioning 1 3 6 4 5 2
  54. ©2018 Wantedly, Inc. class CoordinatedAnimator: NSObject, UIViewImplicitlyAnimating { … func

    startAnimation() { animators.forEach { $0.startAnimation() } } func pauseAnimation() { animators.forEach { $0.pauseAnimation() } } func finishAnimation(at finalPosition: UIViewAnimatingPosition) { animators.forEach { $0.finishAnimation(at: finalPosition) } } … ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ PresentationAnimationController UIViewController AnimatedTransitioning 1 3 6 4 5 2
  55. ©2018 Wantedly, Inc. class PresentationAnimationController: NSObject, UIViewControllerAnimatedTransitioning { func interruptibleAnimator(using

    transitionContext: UIViewControllerContextTransitioning ) -> UIViewImplicitlyAnimating { … var animators: [UIViewPropertyAnimator] = [] … let prioritizedAnimators = self.prioritizedAnimators(from: animators) let animator = CoordinatedAnimator(primaryAnimator: prioritizedAnimators.primary, secondaryAnimators: prioritizedAnimators.secondary) animator.addCompletion { position in let didComplete = position == .end transitionContext.completeTransition(didComplete) } transitionAnimator = animator return animator } … ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ PresentationAnimationController UIViewController AnimatedTransitioning 1 3 6 4 5 2
  56. ©2018 Wantedly, Inc. ͦͷଞ w Interaction Controllerͷ࣮૷ w ભҠલޙͷviewͷؔ࿈෇͚ w

    ભҠ։࢝લͷviewͷߋ৽ w ΩʔϑϨʔϜΞχϝʔγϣϯͷఆٛ https://github.com /hedjirog/CustomPresentation
  57. ©2018 Wantedly, Inc. ·ͱΊ w ੹຿Λҙࣝͨ͠Ϋϥεͷ෼ׂ w viewΛอ࣋ͨ͠controllerͰΞχϝʔγϣϯͱδΣενϟΛఆٛՄೳʹ͢Δ޻෉ w view

    controller͕ϓϩτίϧʹ४ڌ͢Δ͜ͱΛอূͤ͞ΔͨΊ޻෉ w action controllerʹ͓͚ΔΞχϝʔγϣϯͷू໿ͷख๏ w ू໿ͨ͠ΞχϝʔγϣϯΛ࿈ಈ੍ͤͯ͞ޚ͢Δख๏
  58. ©2018 Wantedly, Inc.