自定义转场

在iOS中,自定义转场动画可以通过实现 UIViewControllerAnimatedTransitioning 协议来为模态(modal)和推送(push)转场提供自定义动画。以下是这两种转场的具体实现方式:

1. 自定义模态转场

Step 1: 创建转场代理

创建一个遵循 UIViewControllerAnimatedTransitioning 协议的类:

import UIKit

class CustomModalTransition: NSObject, UIViewControllerAnimatedTransitioning {
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.5 // 设置转场的持续时间
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let fromViewController = transitionContext.viewController(forKey: .from),
              let toViewController = transitionContext.viewController(forKey: .to) else { return }
        
        let containerView = transitionContext.containerView
        containerView.addSubview(toViewController.view)
        
        // 设置初始状态
        toViewController.view.alpha = 0.0
        
        UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
            // 进行动画
            toViewController.view.alpha = 1.0
        }) { _ in
            // 完成转场
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        }
    }
}

Step 2: 设置转场代理

在要展示模态的 ViewController 中设置转场代理:

class FirstViewController: UIViewController, UIViewControllerTransitioningDelegate {
    func presentModal() {
        let secondVC = SecondViewController()
        secondVC.modalPresentationStyle = .custom
        secondVC.transitioningDelegate = self
        present(secondVC, animated: true, completion: nil)
    }

    func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return CustomModalTransition()
    }

    func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        return CustomModalTransition() // 也可以实现dismiss动画
    }
}

2. 自定义推送转场

Step 1: 创建转场代理

创建一个遵循 UIViewControllerAnimatedTransitioning 协议的类,类似于模态转场:

class CustomPushTransition: NSObject, UIViewControllerAnimatedTransitioning {
    func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return 0.5
    }

    func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let fromViewController = transitionContext.viewController(forKey: .from),
              let toViewController = transitionContext.viewController(forKey: .to) else { return }
        
        let containerView = transitionContext.containerView
        containerView.addSubview(toViewController.view)
        
        // 设置初始状态
        toViewController.view.transform = CGAffineTransform(translationX: containerView.bounds.width, y: 0)
        
        UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: {
            // 进行动画
            fromViewController.view.transform = CGAffineTransform(translationX: -containerView.bounds.width, y: 0)
            toViewController.view.transform = .identity
        }) { _ in
            // 完成转场
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        }
    }
}

Step 2: 设置转场代理

在使用 UINavigationControllerViewController 中设置转场代理:

class FirstViewController: UIViewController, UINavigationControllerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationController?.delegate = self
    }

    func pushNextViewController() {
        let nextVC = SecondViewController()
        navigationController?.pushViewController(nextVC, animated: true)
    }

    func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
        if operation == .push {
            return CustomPushTransition()
        }
        return nil
    }
}
posted @ 2024-09-13 09:11  looxy  阅读(38)  评论(0)    收藏  举报