| | |
| | | // |
| | | // 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) |
| | | } |
| | | } |
| | | |