杨锴
2025-05-11 7453d2d0cef415b34323d1b91e6cfa4a6ba31178
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
//
//  TransitionUtil.swift
//  WanPai
//
//  Created by 无故事王国 on 2023/11/23.
//
 
import Foundation
 
///通用转场工具类
class TransitionUtil: NSObject {
                ///转场类型
                var transitionType: TransitionType?
                //交互转场
                var interactive = false
                let interactionTransition = UIPercentDrivenInteractiveTransition()
 
                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)
 
                                                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)
}
 
enum TabBarOperationDirection {
                case left
                case right
}
 
enum ModalOperation {
                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(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 interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
                                return interactive ? self.interactionTransition : nil
                }
}
 
/// 自定义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, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
                                return interactive ? self.interactionTransition : nil
                }
}
 
/// 自定义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, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
                                return interactive ? self.interactionTransition : nil
                }
}
 
extension TransitionUtil: UIViewControllerAnimatedTransitioning {
                //控制转场动画执行时间
                func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
                                return 0.5
                }
 
                //执行动画的地方,最核心的方法。
                func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
                                transitionAnimation(transitionContext: transitionContext)
                }
}