$30 off During Our Annual Pro Sale. View Details »

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

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

Jiro Nagashima

September 02, 2018
Tweet

More Decks by Jiro Nagashima

Other Decks in Technology

Transcript

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

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

    ͕࿈ಈ  γʔτͱϥϕϧͷҠಈ ֦େॖখ   γʔτͷؙ֯  ϥϕϧͷೱ୶  ϥϕϧͷೱ୶  Ϙλϯͷೱ୶  എܠͷೱ୶
  3. ©2018 Wantedly, Inc. UIViewControllerTransitioningDelegate w 3ͭͷ DPOUSPMMFS Λܾఆ͢ΔϝιουΛ࣋ͭϓϩτίϧ • Presentation

    Controller • Animation Controller • Interaction Controller w ભҠઌͷ view controller ͷ transitioningDelegate ϓϩύςΟʹઃఆ ը໘ભҠͷ࣮૷ʹར༻͢ΔAPI
  4. ©2018 Wantedly, Inc. UIViewControllerAnimatedTransitioning w ભҠͷΞχϝʔγϣϯΛܾఆ͢ΔϝιουΛ࣋ͭϓϩτίϧ w ϓϩτίϧʹ४ڌͨ͠ animation controller

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

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

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

    Controller UIViewController AnimatedTransitioning UIPresentationController UIPercentDrivenInteractiveTransition UIViewController InteractiveTransitioning Protocol Class
  8. ©2018 Wantedly, Inc. جຊͷ3ͭͷΫϥε 1. PresentationController • UIPresentationController ͷαϒΫϥε •

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

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

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

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

    func transitionAnimators(operation: PresentationOperation, duration: TimeInterval) -> [UIViewPropertyAnimator] } Ξχϝʔγϣϯͷఆٛ Presentation AnimatedTransitioning
  13. ©2018 Wantedly, Inc. δΣενϟͷఆٛ Wiew Λอ࣋͢Δ controller ͰఆٛՄೳʹ͢Δ w δΣενϟʔͷఆٛʹ͸WJFXͷࢀর͕ඞཁ

    w interaction controller͕ભҠݩ΍ભҠઌͷviewͷߏ଄Λ஌Βͳͯ͘΋ྑ͍Α͏ʹ͍ͨ͠ w δΣενϟʔ͸controllerͰఆٛΛͯ͠ϓϩτίϧΛհͯ͠ू໿Մೳʹ͢Δ Presentation InteractiveTransitioning
  14. ©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
  15. ©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)
  16. ©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
  17. ©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
  18. ©2018 Wantedly, Inc. private func presentSecondViewController() { let presentationController =

    PresentationController(presentedViewController: secondViewController, presentingViewController: self) secondViewController.transitioningDelegate = presentationController present(secondViewController, animated: true) } ϓϩτίϧʹ४ڌ͢Δ͜ͱͷอূ PresentationController (UIPresentationController) UIViewController TransitioningDelegate
  19. ©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)
  20. ©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)
  21. ©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)
  22. ©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)
  23. ©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
  24. ©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
  25. ©2018 Wantedly, Inc. ू໿ͨ͠Ξχϝʔγϣϯͷ࿈ಈ UIViewImplicitlyAnimating ʹ४ڌͨ͠Ξχϝʔγϣϯ͕ඞཁ w ΧελϜͷΞχϝʔγϣϯΛఆٛ w ෳ਺ͷUIViewPropertyAnimatorΛΠχγϟϥΠβҾ਺Ͱड͚औΔ

    w Ξχϝʔγϣϯͷ੍ޚ໋ྩʹैͬͯू໿ͨ͠ΞχϝʔγϣϯΛ࿈ಈͤͯ͞ಈ͔͢ PresentationAnimationController UIViewController AnimatedTransitioning 1 3 6 4 5 2
  26. ©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
  27. ©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
  28. ©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
  29. ©2018 Wantedly, Inc. ͦͷଞ w Interaction Controllerͷ࣮૷ w ભҠલޙͷviewͷؔ࿈෇͚ w

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

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