ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • iOS) Presentation 과 Transition 그리고 Animation... (3)
    iOS 2020. 8. 19. 13:58

    Custom Transition

    transtion을 구성하는 6가지의 객체

    - Animation Controller - Transtion Animation을 구현 UIViewControllerAnimatedTransitioning 프로토콜을 통해 구현

    transition 시간과 animation을 구현하는 두개의 필수 메소드를 가지고 있음.

    - Presentation Controller - 새로운 화면을 구성할 frame을 설정 하고 custom View를 관리

    - Interactive Animator - interactive transition을 구현하는 객체. UIViewcontrollerInteractiveTransition + Gesture Recognizer 로 구현

    - Transition Delegate - UIKit이 transition delegate에게 요청한 animator를 리턴해주면 기본 transition 대신 직접 구현한 animator 사용. UIViewControllerTransitioningDelegate 프로토콜로 구현

    - Transitioning Context - transition이 시작 되기 전에 생성 되며, transition에 필요한 속성을 context에 저장한다. UIViewControllerContextTransitioning 프로토콜을 구현한 객체. 직접 구현하는 경우는 거의 없고 animator로 전달 되는 context를 사용

    - Transition Coordinator - Transition을 실행 할 때 Animation 구현 할 때 활용. 실행중인 transition에 대한 정보 제공. UIKit이 자동으로 생성한 객체를 사용한다. UIViewControllerTransitionCoordinatorContext 프로토콜

    Transition 과정

    1. View Controller는 새로운 화면을 전환 하기 전에 UIKit을 통해 Transition delegate에게 animator(Animation Controller)를 요청한다. 요청 시 delegate 구현되어 있지 않거나 nil이 반환 되면 (custom transition이 아니라면) 기본 transition을 실행 한다.
    2. 이때 animator를 리턴 하면 custom transition을 시작 한다.
    3. delegate에게 interactive animator를 요청하고 최종 적으로 transition 방식을 결정한다.
    4. transitioning context가 생성 되고 transition에 필요한 정보들이 context에 저장된다.
    5. context는 animator로 전달 되고 transition 실행 시간을 확인 한 다음 animation 실행.
    6. animation이 완료 되면 transitioning context에서 completeTransition(_:)을 호출하면 presentation이 완료 된다.

    Custom Transition 만들기

    Custom Transition을 이용해서 MainViewController에 있는 collectionView의 cell을 확대 해서 새로운 뷰에 나타내는 transition을 구현 해보자.

    mainViewController

    Animation Controller를 보기전에 rootVC가 되는 ViewController를 보자.

    Animator인 AnimationController 객체를 하나 만들어준다.

    UIViewControllerTransitioningDelegate

    extension을 통해 UIViewControllerTransitionDelegate 프로토콜을 채택 해주고, present 될 때와 dismiss 될 때 Animation Controller를 리턴 해준다.

    prepare

    segue를 통해 animator에 segue로 넘어가는 cell image 데이터와 cell IndexPath를 넘겨준다.

    ZoomAnimationViewController

    transition 정보를 가지고 있는 Animation Controller를 만들어 보자.
    우선 UIViewControllerAnimatedTransitioning 프로토콜을 채택한 NSObject Class를 하나 만들어 준다.

    필수 메소드 두 가지가 존재 한다.

    - transitionDuration()
    transition의 시간을 리턴 해준다.

    - animateTransition(using transitionContext: UIViewControllerContextTransitioning) transition의 핵심 메소드. transition에서 이루어지는 모든 애니메이션이 이 안에서 작동 된다. 이때 transitionContext를 활용 해서 viewController, View, contentView에 접근 할 수 있다.

    앞서 했던 presentation처럼 transition도 presenting과 dismiss 동작 두가지로 나뉜다.

    presenting과 dismiss를 따로 메소드화 시켜서 사용 할 수도 있지만, Bool타입의 변수 하나를 선언해서 상태를 나누자.

    if 블록 안에는 presenting 될 때, else 블록엔 dismiss 될 때의 transition을 구현 할 것이다.

    화면에 접근하고 애니메이션을 구성하는데에 있어서 우리가 필요한 것은 4가지이다.

    - transition view를 담당하는 containerView

    - 원래의 ViewController

    - presented될 ViewContoller

    - 그리고 transition animation이 구현될 새로운 imageView
    이중 위의 세 가지 모두 transitionContext를 통해 접근 할 수 있다.

    toView는 presented 될 View이고 fromVC에선 처음 cell의 위치를 가져온다.

    toView를 containerView에 추가하고 fromVC에서 cell의 위치를 가져온 후 새로운 imageView를 만들어서 containerView에 추가 해준다.

    transition animation이 진행 되는 flow

    1. transition이 시작 된다.
    2. transitionContext를 통해 containerView에 animation이 진행 될 새로운 imageView를 추가해 준다.
    3. containerView에 나타 날 toView를 추가 해준다.
    4. UIView.animation() 메소드를 통해 animation이 시작 된다.
    5. containerView의 imageView가 나타난다.
    6. imageView의 animation이 진행된다.
    7. imageView의 alpha가 0이 된다.
    8. containerView의 toView의 alpha가 1이 된다.
    9. imageView를 containerView에서 지우고 transitionContext에서 CompleteTransition 메소드를 실행시킨다.
    10. transtion이 끝난다.

    위의 flow 대로 코드를 구성 해보자.

    주목 해야 할 것은 imageView의 시작 startFrame이다.
    처음 imageView의 시작 frame을 잡아 줄 때, targetCell의 frame으로 지정했다.

    잘못된 좌표 설정

    엥? imageView의 startFrame이 이상하다.

    클릭한 targetCell 즉, collectionView Cell의 superView는 collectionView이고 collectionView Cell의 좌표는 collectionView 안의 좌표이다.

    따라서 collectionView frame안에서 cell의 좌표는 (0, 0) 이기 때문에 imageView가 추가된 containerView안에서의 (0, 0)은 위의 이미지와 같이 화면 전체 frame의 (0, 0)이다.

    따라서 convert 메소드를 통해 원하는 객체의 좌표공간(imageListCollectionView)의 rect 정보(targetCell)를 원하는 좌표공간(fromView)의 rect좌표로 변환 해준다.

    각 좌표계
    완성 된 presenting transition

    dismiss transition의 경우 presenting과 달리 toVC와 fromVC를 반대로 타입 캐스팅 해주면 된다.

    마치며 자연스럽고 미려한 transition을 위해선 fromView와 toView의 view의 위치가 가장 중요하다.

     

     

    전체 코드: https://github.com/uiyeonShin/Transition-Animation/tree/master/PracTransition/TransitionControllers

    'iOS' 카테고리의 다른 글

    iOS) Network -ATS  (0) 2020.09.24
    iOS) Data encoding to utf8  (0) 2020.08.31
    iOS) dismiss(animated:completion:)의 새로운 발견  (0) 2020.08.14
    iOS) TableView refresh - index out of range 오류  (0) 2020.08.10
    iOS) Network - ATS  (0) 2020.08.10

    댓글

Designed by Tistory.