Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- rxswift
- Refactoring
- ios
- RxCocoa
- 스위프트
- Protocol
- Xcode
- Observable
- 리팩토링
- combine
- clean architecture
- UICollectionView
- uitableview
- collectionview
- swift documentation
- tableView
- swiftUI
- HIG
- SWIFT
- 클린 코드
- uiscrollview
- MVVM
- 리펙토링
- 애니메이션
- Human interface guide
- Clean Code
- map
- 리펙터링
- ribs
- UITextView
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 화면 전환 애니메이션 커스텀 방법 (UIPercentDrivenInteractiveTransition, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate) 본문
iOS 응용 (swift)
[iOS - swift] 화면 전환 애니메이션 커스텀 방법 (UIPercentDrivenInteractiveTransition, UIViewControllerAnimatedTransitioning, UIViewControllerTransitioningDelegate)
jake-kim 2022. 3. 20. 14:00
화면전환 애니메이션 커스텀 아이디어
- VC1 -> VC2로 화면전환 하는 경우, VC2 인스턴스의 화면전환 델리게이트를 conform하여 애니메이션을 넣어주는 것
- delegate 부분
// ViewController.swift (=VC1)
@objc private func didTapNextButton() {
let vc2 = VC2()
vc2.transitioningDelegate = self // <- 델리게이트 conform
vc2.modalPresentationStyle = .fullScreen
self.present(vc2, animated: true)
}
- delegate는 UIViewControllerTransitioningDelegate
- present와 dismiss 따로 구현
- 보통 UIViewControllerTransitioningDelegate 프로토콜을 구현하는 커스텀 클래스 인스턴스를 주입
extension ViewController: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
MyPresentTransition()
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
nil
}
}
UIViewControllerTransitioningDelegate 구현하는 클래스
- UIPercentDrivenInteractiveTransition는 NSObject 형태의 클래스가 필요
import UIKit
final class MyPresentTransition: NSObject {
}
- 2가지 메소드 구현
extension MyPresentTransition: UIViewControllerAnimatedTransitioning {
// 애니메이션 동작 시간
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
}
// 애니메이션 정의
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
}
}
- 애니메이션에 사용될 상수 선언
private enum Constants {
static let duration = 1.0
static let affineTransform = CGAffineTransform(scaleX: 0.5, y: 0.5)
}
- animateTransition 메소드 내부 구현
- 애니메이션이 실행 될 toView와 그의 컨테이너인 containerView 획득
- 애니메이션 시작할 때의 toView의 위치를 containerView와 동일하게 설정
- 커스텀 애니메이션 정의
* 아래에서 내려오는 animateKeyframes 애니메이션 사용 방법은 이전 포스팅 글 참고
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
// 1. 애니메이션에 적용할 뷰 획득
let containerView = transitionContext.containerView
guard let toView = transitionContext.view(forKey: .to) else { return }
containerView.addSubview(toView)
containerView.bringSubviewToFront(toView)
// 2. 초기 위치 설정
toView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
toView.leftAnchor.constraint(equalTo: containerView.leftAnchor),
toView.rightAnchor.constraint(equalTo: containerView.rightAnchor),
toView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
toView.topAnchor.constraint(equalTo: containerView.topAnchor),
])
// 3. 커스텀 애니메이션 정의
UIView.animateKeyframes(
withDuration: Constants.duration,
delay: 0,
animations: {
UIView.addKeyframe(
withRelativeStartTime: 0 / 2,
relativeDuration: 1 / 2,
animations: {
toView.transform = Constants.affineTransform
}
)
UIView.addKeyframe(
withRelativeStartTime: 1 / 2,
relativeDuration: 1 / 2,
animations: {
toView.transform = .identity
}
)
},
completion: { transitionContext.completeTransition($0) }
)
}
- 완성된 MyPresentTransition 클래스를 화면전환할 때 주입
// ViewController.swift (=VC1)
@objc private func didTapNextButton() {
let vc2 = VC2()
vc2.transitioningDelegate = self // <- 델리게이트 conform
vc2.modalPresentationStyle = .fullScreen
self.present(vc2, animated: true)
}
...
extension ViewController: UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
MyPresentTransition() // <- 사용
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
nil
}
}
* dismiss에도 커스텀 애니메이션을 구현한다면, toView가 아닌 fromView를 얻어서 구현
import UIKit
final class MyDismissTransition: NSObject {
}
extension MyDismissTransition: UIViewControllerAnimatedTransitioning {
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
0.5
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
// 사라지는 뷰
guard let fromView = transitionContext.view(forKey: .from) else { return }
UIView.animate(
withDuration: 0.5,
animations: { fromView.alpha = 0 },
completion: { completed in transitionContext.completeTransition(completed) }
)
}
}
* 전체 코드: https://github.com/JK0369/ExTransitionAnimation
* 참고
'iOS 응용 (swift)' 카테고리의 다른 글
Comments