모달 전환의 애니메이션 사용자 정의

16380 단어 iOSSwift

소개



앱에서 모달 전환할 때 몇 가지 기본 애니메이션이 제공되지만, 다른 애니메이션을 사용하고 싶을 때 직접 사용자 지정할 수 있는 것 같습니다.
이번에는 UIViewControllerAnimatedTransitioning 를 사용하여 옆으로 스 와이프했을 때와 같은 애니메이션을 구현해 보았습니다.

구현 이미지





코드



모달을 호출하는 쪽 코드



BaseViewController.swift
import UIKit

class BaseViewController: UIViewController {

    @IBOutlet weak var buttonShow: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    @IBAction func showModalView(_ sender: Any) {
        guard let modalVC = UIStoryboard(name: String(describing: CustomModalViewController.self), bundle: nil)
                .instantiateInitialViewController() as? CustomModalViewController else { return }

        modalVC.modalPresentationStyle = .fullScreen
        present(modalVC, animated: true)
    }
}

모달로 호출되는 쪽 코드



CustomModalViewController.swift
import UIKit

class CustomModalViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        transitioningDelegate = self
    }

    @IBAction func touchCloseButton(_ sender: Any) {
        dismiss(animated: true, completion: nil)
    }

}

// モーダルとして呼び出す側に「UIViewControllerTransitioningDelegate」を継承させる。
// MARK: UIViewControllerTransitioningDelegate
extension CustomModalViewController: UIViewControllerTransitioningDelegate {

    // presentのときに呼ばれる
    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return CustomAnimater(animationMode: .present)
    }

    // dismissのときに呼ばれる
    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return CustomAnimater(animationMode: .dismiss)
    }
}

애니메이션을 정의하는 클래스



CustomAnimeter.swift
class CustomAnimater: NSObject {

    // 開くと閉じるしかないので、enumで定義しておくと楽
    enum AnimationMode {
        case present, dismiss
    }
    private let animationMode: AnimationMode
    private let duration = 0.3

    init(animationMode: AnimationMode) {
        self.animationMode = animationMode
    }
}

extension CustomAnimater: UIViewControllerAnimatedTransitioning {

    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return duration
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        if animationMode == .present {
            guard let toView = transitionContext.view(forKey: .to) else { return }
            guard let fromView = transitionContext.view(forKey: .from) else { return }
            transitionContext.containerView.addSubview(toView)
            toView.alpha = 0.0
            toView.transform = CGAffineTransform(translationX:fromView.bounds.size.width * 0.8 , y: 0)
            UIView.animate(withDuration: 0.5, delay: 0) { [weak self] in
                guard let _ = self else { return }
                toView.transform = CGAffineTransform(translationX: 0, y: 0)
                toView.alpha = 1.0
            } completion: { finish in
                toView.transform = .identity
                transitionContext.completeTransition(finish)
            }
        } else {
            guard let toView = transitionContext.view(forKey: .to) else { return }
            guard let fromView = transitionContext.view(forKey: .from) else { return }
            transitionContext.containerView.addSubview(toView)
            transitionContext.containerView.addSubview(fromView)
            fromView.alpha = 1
            UIView.animate(withDuration: 0.5, delay: 0) {
                fromView.alpha = 0.0
                fromView.transform = CGAffineTransform(translationX:-fromView.bounds.size.width * 0.8 , y: 0)
            } completion: { finish in
                // transformをもとに戻さないとバグの要因になることがあるみたい
                fromView.transform = .identity
                transitionContext.completeTransition(finish)
            }
        }
    }
}

좋은 웹페이지 즐겨찾기