杨锴
2024-10-09 1f08239dd60c05f1eb6eb9b3122aa23cd700348b
WanPai/Config/TransitionUtil.swift
@@ -1,165 +1,165 @@
   //
   //  TransitionUtil.swift
   //  WanPai
   //
   //  Created by 无故事王国 on 2023/11/23.
   //
//
//  TransitionUtil.swift
//  WanPai
//
//  Created by 无故事王国 on 2023/11/23.
//
import Foundation
   ///通用转场工具类
///通用转场工具类
class TransitionUtil: NSObject {
      ///转场类型
   var transitionType: TransitionType?
      //交互转场
   var interactive = false
   let interactionTransition = UIPercentDrivenInteractiveTransition()
            ///转场类型
            var transitionType: TransitionType?
            //交互转场
            var interactive = false
            let interactionTransition = UIPercentDrivenInteractiveTransition()
   override init() {
      super.init()
            override init() {
                        super.init()
   }
      //MARK:  ------------  不同类型的转场  ------------
   private func transitionAnimation(transitionContext: UIViewControllerContextTransitioning) {
         //获得容器视图(转场动画发生的地方)
      let containerView = transitionContext.containerView
         //动画执行时间
      let duration = self.transitionDuration(using: transitionContext)
         //fromVC (即将消失的视图)
      let fromVC = transitionContext.viewController(forKey: .from)!
      let fromView = fromVC.view!
         //toVC (即将出现的视图)
      let toVC = transitionContext.viewController(forKey: .to)!
      let toView = toVC.view!
      var offset = containerView.frame.width
      var fromTransform = CGAffineTransform.identity
      var toTransform = CGAffineTransform.identity
      switch transitionType {
         case .modal(let operation):
            offset = containerView.frame.height
            let fromY = operation == .presentation ? 0 : offset
            fromTransform = CGAffineTransform(translationX: 0, y: fromY)
            let toY = operation == .presentation ? offset : 0
            toTransform = CGAffineTransform(translationX: 0, y: toY)
            if operation == .presentation {
               containerView.addSubview(toView)
            }
         case .navigation(let operation):
            offset = operation == .push ? offset : -offset
            fromTransform = CGAffineTransform(translationX: -offset, y: 0)
            toTransform = CGAffineTransform(translationX: offset, y: 0)
            containerView.insertSubview(toView, at: 0)
               //containerView.addSubview(toView)
            //MARK:  ------------  不同类型的转场  ------------
         case .tabBar(let direction):
            offset = direction == .left ? offset : -offset
            fromTransform = CGAffineTransform(translationX: offset, y: 0)
            toTransform = CGAffineTransform(translationX: -offset, y: 0)
            containerView.addSubview(toView)
            private func transitionAnimation(transitionContext: UIViewControllerContextTransitioning) {
                        //获得容器视图(转场动画发生的地方)
                        let containerView = transitionContext.containerView
                        //动画执行时间
                        let duration = self.transitionDuration(using: transitionContext)
         case nil:
            break
      }
                        //fromVC (即将消失的视图)
                        let fromVC = transitionContext.viewController(forKey: .from)!
                        let fromView = fromVC.view!
                        //toVC (即将出现的视图)
                        let toVC = transitionContext.viewController(forKey: .to)!
                        let toView = toVC.view!
      toView.transform = toTransform
      UIView.animate(withDuration: duration, animations: {
         fromView.transform = fromTransform
         toView.transform = .identity
      }) { (finished) in
         fromView.transform = .identity
         toView.transform = .identity
            //考虑到转场中途可能取消的情况,转场结束后,恢复视图状态。(通知是否完成转场)
         let wasCancelled = transitionContext.transitionWasCancelled
         transitionContext.completeTransition(!wasCancelled)
      }
   }
                        var offset = containerView.frame.width
                        var fromTransform = CGAffineTransform.identity
                        var toTransform = CGAffineTransform.identity
                        switch transitionType {
                                    case .modal(let operation):
                                                offset = containerView.frame.height
                                                let fromY = operation == .presentation ? 0 : offset
                                                fromTransform = CGAffineTransform(translationX: 0, y: fromY)
                                                let toY = operation == .presentation ? offset : 0
                                                toTransform = CGAffineTransform(translationX: 0, y: toY)
                                                if operation == .presentation {
                                                            containerView.addSubview(toView)
                                                }
                                    case .navigation(let operation):
                                                offset = operation == .push ? offset : -offset
                                                fromTransform = CGAffineTransform(translationX: -offset, y: 0)
                                                toTransform = CGAffineTransform(translationX: offset, y: 0)
                                                containerView.insertSubview(toView, at: 0)
                                                //containerView.addSubview(toView)
                                    case .tabBar(let direction):
                                                offset = direction == .left ? offset : -offset
                                                fromTransform = CGAffineTransform(translationX: offset, y: 0)
                                                toTransform = CGAffineTransform(translationX: -offset, y: 0)
                                                containerView.addSubview(toView)
                                    case nil:
                                                break
                        }
                        toView.transform = toTransform
                        UIView.animate(withDuration: duration, animations: {
                                    fromView.transform = fromTransform
                                    toView.transform = .identity
                        }) { (finished) in
                                    fromView.transform = .identity
                                    toView.transform = .identity
                                    //考虑到转场中途可能取消的情况,转场结束后,恢复视图状态。(通知是否完成转场)
                                    let wasCancelled = transitionContext.transitionWasCancelled
                                    transitionContext.completeTransition(!wasCancelled)
                        }
            }
}
   ///转场类型
///转场类型
enum TransitionType {
      //导航栏
   case navigation(_ operation: UINavigationController.Operation)
      //tabBar切换
   case tabBar(_ direction: TabBarOperationDirection)
      //模态跳转
   case modal(_ operation: ModalOperation)
            //导航栏
            case navigation(_ operation: UINavigationController.Operation)
            //tabBar切换
            case tabBar(_ direction: TabBarOperationDirection)
            //模态跳转
            case modal(_ operation: ModalOperation)
}
enum TabBarOperationDirection {
   case left
   case right
            case left
            case right
}
enum ModalOperation {
   case presentation
   case dismissal
            case presentation
            case dismissal
}
   ///自定义模态转场动画时使用
///自定义模态转场动画时使用
extension TransitionUtil: UIViewControllerTransitioningDelegate {
   func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
      self.transitionType = .modal(.presentation)
      return self
   }
            func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
                        self.transitionType = .modal(.presentation)
                        return self
            }
   func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
      self.transitionType = .modal(.dismissal)
      return self
   }
            func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
                        self.transitionType = .modal(.dismissal)
                        return self
            }
      //interactive false:非交互转场, true: 交互转场
   func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
      return interactive ? self.interactionTransition : nil
   }
            //interactive false:非交互转场, true: 交互转场
            func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
                        return interactive ? self.interactionTransition : nil
            }
      //interactive false:非交互转场, true: 交互转场
   func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
      return interactive ? self.interactionTransition : nil
   }
            //interactive false:非交互转场, true: 交互转场
            func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
                        return interactive ? self.interactionTransition : nil
            }
}
   /// 自定义navigation转场动画时使用
/// 自定义navigation转场动画时使用
extension TransitionUtil: UINavigationControllerDelegate {
   func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
      self.transitionType = .navigation(operation)
      return self
   }
            func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
                        self.transitionType = .navigation(operation)
                        return self
            }
   func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
      return interactive ? self.interactionTransition : nil
   }
            func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
                        return interactive ? self.interactionTransition : nil
            }
}
   /// 自定义tab转场动画时使用
/// 自定义tab转场动画时使用
extension TransitionUtil: UITabBarControllerDelegate {
   func tabBarController(_ tabBarController: UITabBarController, animationControllerForTransitionFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
      let fromIndex = tabBarController.viewControllers?.firstIndex(of: fromVC) ?? 0
      let toIndex = tabBarController.viewControllers?.firstIndex(of: toVC) ?? 0
      let direction: TabBarOperationDirection = fromIndex < toIndex ? .right : .left
      self.transitionType = .tabBar(direction)
      return self
   }
            func tabBarController(_ tabBarController: UITabBarController, animationControllerForTransitionFrom fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
                        let fromIndex = tabBarController.viewControllers?.firstIndex(of: fromVC) ?? 0
                        let toIndex = tabBarController.viewControllers?.firstIndex(of: toVC) ?? 0
                        let direction: TabBarOperationDirection = fromIndex < toIndex ? .right : .left
                        self.transitionType = .tabBar(direction)
                        return self
            }
   func tabBarController(_ tabBarController: UITabBarController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
      return interactive ? self.interactionTransition : nil
   }
            func tabBarController(_ tabBarController: UITabBarController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
                        return interactive ? self.interactionTransition : nil
            }
}
extension TransitionUtil: UIViewControllerAnimatedTransitioning {
      //控制转场动画执行时间
   func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
      return 0.5
   }
            //控制转场动画执行时间
            func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
                        return 0.5
            }
      //执行动画的地方,最核心的方法。
   func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
      transitionAnimation(transitionContext: transitionContext)
   }
            //执行动画的地方,最核心的方法。
            func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
                        transitionAnimation(transitionContext: transitionContext)
            }
}