오늘은 화려한 화면이동을 위해 커스텀 화면전환 애니메이션에 대해 공부해보려 한다.
공식 문서
UIViewControllerAnimatedTransitioning
UIPercentDrivenInteractiveTransition
UIViewControllerTransitioningDelegate
custom view controller transition을 implement하기 위한 Protocol이다.
해당 프로토콜은
func transitionDuration(using:)
func animateTransition(using :)
을 필수로 구현해야 한다.
보통 Animation을 담당하는 클래스가 준수한다.
ViewController과 다른 View간의 interactive한 animation을 발생시키는 Class이다.
ViewController간의 interactive한 transition을 관리하는 Protocol이다.
화면을 이동하는 ViewController에서 구현해준다.
먼저 Animation을 처리할 클래스를 선언해야한다.
UIViewControllerAnimatedTransitioning
프로토콜을 준수하여 애니메이션과 듀레이션을 정의해주어야 한다.
동작 방식을 살펴보자
/// 실제 코드는 레이웬더리치 블로그에
import UIKit
class AnimationController: NSObject, UIViewControllerAnimatedTransitioning {
// start point for animation
private let originFrame: CGRect
// 시작할 프레임을 가져와서 스냅샷을 만들기 위해 필요
init(originFrame: CGRect) {
self.originFrame = originFrame
}
// 애니메이션 동작시간
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 1
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
/* 1 - 다음 필요한 항목들을 가져온다.
1. fromView와 toView를 context
2. fromView와 toView사이에 보여질 snapshot
3. transition에서 보여질 containerView
4. toView가 마지막으로 보여질 finalFrame
*/
/* 2 - 애니메이션 전처리를 해준다.
1. containerView에는 fromView만 들어가있으므로 toView와 snapshot을 추가
2. toView를 숨김처리
3. 애니메이션 설정
4. 듀레이션 설정
*/
/* 3 - 애니메이션을 처리해준다.
1. 시작프레임과 끝프레임, 시간, completion등을 처리
*/
}
}
A 뷰컨에서 B뷰컨으로 transition할 경우,
A 뷰컨에 UIViewControllerTransitioningDelegate
을 채택해주고,
B 뷰컨의 transitioningDelegate를 A 뷰컨으로 설정해주어야한다.
다음과 같이 설정하면 된다.
import UIKit
class CardViewController: UIViewController {
static let cardCornerRadius: CGFloat = 25
// UI 그리고 세팅
// destination으로 갈때 destination의 delegate를 self로
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segueIdentifier(for: segue) == .reveal,
let destinationViewController = segue.destination as? RevealViewController {
destinationViewController.transitioningDelegate = self
}
}
// Animation 처리를 담당할 클래스, Dismiss를 담당할 클래스를 각각 정의해준다.
extension CardViewController: UIViewControllerTransitioningDelegate {
func animationController(
forPresented presented: UIViewController,
presenting: UIViewController,
source: UIViewController
) -> UIViewControllerAnimatedTransitioning? {
return FlipPresentAnimationController(originFrame: cardView.frame)
}
func animationController(
forDismissed dismissed: UIViewController
) -> UIViewControllerAnimatedTransitioning? {
guard let _ = dismissed as? RevealViewController else {
return nil
}
return FlipDismissAnimationController(destinationFrame: cardView.frame)
}
}
이렇게 할 경우 다음과 같은 애니메이션을 볼 수 있다.