꿀똥벌레
꿀똥벌레 개발 블로그
꿀똥벌레
전체 방문자
오늘
어제
  • 분류 전체보기 (90)
    • JAVA (17)
    • SPRING (14)
    • Elasticsearch (4)
    • GRADLE (2)
    • HTML, CSS (0)
    • JAVASCRIPT (0)
    • GIT (1)
    • Vue.js (1)
    • server (1)
    • Python (0)
    • IT리뷰 (0)
    • 인프라 (6)
    • IOS (21)
    • 디자인패턴 (20)
    • Kafka (1)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • maxConnPerRoute
  • SWIFT
  • KEEPALIVE
  • ES
  • connectionRequestTimeout
  • spring integration
  • persistent connection
  • mappings
  • Index Template
  • elasticsearch
  • persistence connection
  • 인덱스 템플릿
  • Index
  • 스프링 인티그레이션
  • 스프링 인테그레이션
  • 엘라스틱서치
  • java
  • maxConnTotal
  • spring
  • springintegration

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
꿀똥벌레

꿀똥벌레 개발 블로그

IOS

UIKit 커스텀 애니메이션

2022. 12. 20. 16:12

transitioningDelegate

  • 모든 뷰 컨트롤러가 가질 수 있으며, UIViewControllerTransitioningDelegate 프로토콜을 따른다.
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?
  • 위 메소드를 구현하여 애니메이션 컨트롤러를 리턴하게 한다.

UIViewControllerAnimatedTransitioning

  • 애니메이션 컨트롤러 라 칭한다.
  • TransitioningDelegate 가 리턴하는 애니메이션 컨트롤러 객체
  • transitionDuration 을 구현하여 애니메이션 실행 시간을 리턴한다.
  • animateTransition 을 구현하여 fromController -> toController로 트랜지션 시 애니메이션을 직접 정의한다.

TransitioningContext

  • UIViewControllerContextTransitioning 프로토콜을 따른다.
  • 직접 만드는 것이 아닌, 각각 transition이 발생시 마다 UIKit이 생성해서 AnimationController로 전달해준다.
  • 애니메이션 컨트롤러의 animateTransition 메소드의 파라미터로 받는다.

 

트랜지션 프로세스

  1. 트랜지션이 발생한다.
  2. UIKit은 To(보여질) 컨트롤러에게 TransitioningDelegate를 요청한다. 없으면 스탠다드 딜리게이트를 사용한다.
  3. UIKit은 TransitioningDelegate에게 애니메이션 컨트롤러를 요청한다. 만약 nil을 리턴한다면, 디폴트 애니메이션을 사용한다.
    • animationController(forPresented:presenting:source:) 을 통해 요청
  4. UIKit은 TransitioningContext를 생성한다.
  5. UIKit은 애니메이션 컨트롤러에게 애니메이션 지속 시간을 요청한다.
    • transitionDuration(using:)
  6. UIKit은 애니메이션 컨트롤러에 있는 animateTransition(using:) 을 호출하여 애니메이션을 실행한다.
  7. 애니메이션컨트롤러는 TransitionContext의 completeTransition(_:) 를 호출하여 애니메이션이 종료됨을 알린다.

사라지는 트랜지션은 To컨트롤러가 아닌, From컨트롤러를 호출하고(forDismissed), 나머지는 거의 일치한다.

(To -> From 으로 트랜지션 발생하므로, 그에 맞게 애니메이션도 정의 해주어야 한다.)

 

예시

func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
    guard let fromVC = transitionContext.viewController(forKey: .from),
          let toVC = transitionContext.viewController(forKey: .to),
          let snapshot = toVC.view.snapshotView(afterScreenUpdates: true)
    else {
      return
    }
    
    let containerView = transitionContext.containerView
    let finalFrame = transitionContext.finalFrame(for: toVC)
    
    snapshot.frame = originFrame
    snapshot.layer.cornerRadius = CardViewController.cardCornerRadius
    snapshot.layer.masksToBounds = true
    
    containerView.addSubview(toVC.view)
    containerView.addSubview(snapshot)
    toVC.view.isHidden = true
    
    AnimationHelper.perspectiveTransform(for: containerView)
    snapshot.layer.transform = AnimationHelper.yRotation(.pi / 2)
    
    let duration = transitionDuration(using: transitionContext)
    
    //키프레임 기반으로 애니메이션 설정
    UIView.animateKeyframes(
      withDuration: duration, //전체 애니메이션 지속 시간
      delay: 0, // 애니메이션 시작 전 대기 딜레이
      options: .calculationModeCubic, //애니메이션을 어떻게 수행할지에 대한 상수
      animations: { //애니메이션 실제 구현
      //withRelativeStartTime, relativeDuration 은 전부 비율이다. 
      //animateKeyframes 설정시 duration에 대한 비율대로 실행된다.
        UIView.addKeyframe(withRelativeStartTime: 0.0, relativeDuration: 1/3) {
          fromVC.view.layer.transform = AnimationHelper.yRotation(-.pi / 2)
        }
        
        UIView.addKeyframe(withRelativeStartTime: 1/3, relativeDuration: 1/3) {
          snapshot.layer.transform = AnimationHelper.yRotation(0.0)
        }
        
        UIView.addKeyframe(withRelativeStartTime: 2/3, relativeDuration: 1/3) {
          snapshot.frame = finalFrame
          snapshot.layer.cornerRadius = 0
        }
      }, completion: { _ in
      //애니메이션 완료 시 핸들러
        toVC.view.isHidden = false
        snapshot.removeFromSuperview()
        fromVC.view.layer.transform = CATransform3DIdentity
        
        transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
      })
  }

 

참조

https://www.kodeco.com/322-custom-uiviewcontroller-transitions-getting-started

저작자표시 (새창열림)

'IOS' 카테고리의 다른 글

Swift enum  (0) 2022.12.31
Swift 에러 핸들링 (try, catch, throw, throws, do)  (0) 2022.12.28
SwiftUI NavigationView BackButton Custom  (0) 2022.11.05
SwiftUI 에서 UIKit 사용하기  (0) 2022.11.01
NSCollectionLayoutDimension 알아보기  (0) 2022.10.15
    꿀똥벌레
    꿀똥벌레
    개발자 꿀똥벌레 입니다.

    티스토리툴바