-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEdoPopupSWindow.swift
271 lines (223 loc) · 8.87 KB
/
EdoPopupSWindow.swift
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
//
// EdoPopupSWindow.swift
// EdoPopupView
//
// Created by xfg on 2018/3/19.
// Copyright © 2018年 xfg. All rights reserved.
// 弹窗window
/** ************************************************
github地址:https://github.com/choiceyou/FWPopupView
bug反馈、交流群:670698309
***************************************************
*/
import Foundation
import UIKit
public func kPV_RGBA (r:CGFloat, g:CGFloat, b:CGFloat, a:CGFloat) -> UIColor {
return UIColor (red: r/255.0, green: g/255.0, blue: b/255.0, alpha: a)
}
open class EdoPopupSWindow: UIWindow, UIGestureRecognizerDelegate {
/// 单例模式
@objc public class var sharedInstance: EdoPopupSWindow {
struct Static {
static let kbManager = EdoPopupSWindow(frame: UIScreen.main.bounds)
}
if #available(iOS 13.0, *) {
if Static.kbManager.windowScene == nil {
let windowScene = UIApplication.shared.connectedScenes.filter{$0.activationState == .foregroundActive}.first
Static.kbManager.windowScene = windowScene as? UIWindowScene
}
}
return Static.kbManager
}
// 默认false,当为true时:用户拖动外部遮罩层页面可以消失
@objc open var panWildToHide: Bool = false
/// 被隐藏的视图队列(A视图正在显示,接着B视图显示,此时就把A视图隐藏同时放入该队列)
open var hiddenViews: [UIView] = []
/// 将要展示的视图队列(A视图的显示或者隐藏动画正在进行中时,此时如果B视图要显示,则把B视图放入该队列,等动画结束从该队列中拿出来显示)
open var willShowingViews: [UIView] = []
public override init(frame: CGRect) {
super.init(frame: frame)
let rootVC = EdoPopupRootViewController()
rootVC.view.backgroundColor = UIColor.clear
self.rootViewController = rootVC
self.windowLevel = UIWindow.Level.statusBar + 1
// EdoColor.updateDarkModeSetting(self)
let tapGest = UITapGestureRecognizer(target: self, action: #selector(tapGesClick(tap:)))
tapGest.delegate = self
self.addGestureRecognizer(tapGest)
let panGest = UIPanGestureRecognizer(target: self, action: #selector(panGesClick(pan:)))
self.addGestureRecognizer(panGest)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension EdoPopupSWindow {
@objc func tapGesClick(tap: UIGestureRecognizer) {
if let attachView = self.attachView(), !attachView.edoBackgroundAnimating {
for view in attachView.edoMaskView.subviews {
if !self.hiddenViews.contains(view), let popupView = view as? EdoMenuView {
if popupView.currentPopupViewState == .didAppear || popupView.currentPopupViewState == .didAppearAgain {
popupView.hide()
}
}
}
}
}
@objc func panGesClick(pan: UIGestureRecognizer) {
if self.panWildToHide {
self.tapGesClick(tap: pan)
}
}
/// 隐藏全部的弹窗(包括当前不可见的弹窗)
@objc public func removeAllPopupView() {
if let attachView = self.attachView() {
for view in attachView.edoMaskView.subviews {
if let popupView = view as? EdoMenuView {
popupView.hide()
}
}
attachView.hideEdoBackground(self)
}
}
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return touch.view == self.attachView()?.edoMaskView
}
public func attachView() -> UIView? {
if self.rootViewController != nil {
return self.rootViewController?.view
} else {
return nil
}
}
}
class EdoPopupRootViewController: UIViewController {
override var preferredStatusBarStyle: UIStatusBarStyle {
if #available(iOS 13.0, *) {
return UIApplication.shared.windows.first?.windowScene?.statusBarManager?.statusBarStyle ?? UIStatusBarStyle.default
} else {
return UIApplication.shared.statusBarStyle
}
}
override var prefersStatusBarHidden: Bool {
if #available(iOS 13.0, *) {
return UIApplication.shared.windows.first?.windowScene?.statusBarManager?.isStatusBarHidden ?? false
} else {
return UIApplication.shared.isStatusBarHidden
}
}
}
extension UIView {
var edoBackgroundAnimating: Bool {
get {
if let key = edoBackgroundAnimatingKey, let isAnimating = objc_getAssociatedObject(self, key) as? Bool {
return isAnimating
}
return false
}
set {
if let key = edoBackgroundAnimatingKey {
objc_setAssociatedObject(self, key, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
var edoAnimationDuration: TimeInterval {
get {
if let key = edoAnimationDurationKey, let duration = objc_getAssociatedObject(self, key) as? TimeInterval {
return duration
}
return 0.0
}
set {
if let key = edoAnimationDurationKey {
objc_setAssociatedObject(self, key, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
var edoReferenceCount: Int {
get {
if let key = edoReferenceCountKey, let count = objc_getAssociatedObject(self, key) as? Int {
return count
}
return 0
}
set {
if let key = edoReferenceCountKey {
objc_setAssociatedObject(self, key, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
/// 遮罩层颜色
var edoMaskViewColor: UIColor {
get {
if let key = edoBackgroundViewColorKey, let color = objc_getAssociatedObject(self, key) as? UIColor {
return color
}
return kDefaultMaskViewColor
}
set {
if let key = edoBackgroundViewColorKey {
objc_setAssociatedObject(self, key, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
/// 遮罩层
var edoMaskView: UIView {
guard let key = edoBackgroundViewKey else {
return UIView()
}
if let tmpView = objc_getAssociatedObject(self, key) as? UIView {
return tmpView
} else {
let tmpView = UIView(frame: self.bounds)
self.addSubview(tmpView)
tmpView.snp.makeConstraints({ (make) in
make.top.left.bottom.right.equalTo(self)
})
tmpView.alpha = 0.0
tmpView.layer.zPosition = CGFloat(MAXFLOAT)
tmpView.backgroundColor = edoMaskViewColor
objc_setAssociatedObject(self, key, tmpView, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return tmpView
}
}
/// 显示遮罩层
func showEdoBackground(_ popupSWindow: EdoPopupSWindow) {
self.edoReferenceCount += 1
if self.edoReferenceCount > 1 {
self.edoReferenceCount -= 1
return
}
self.edoMaskView.isHidden = false
self.edoMaskView.backgroundColor = self.edoMaskViewColor
if self == popupSWindow.attachView() {
popupSWindow.isHidden = false
popupSWindow.makeKeyAndVisible()
} else if let aa = self as? UIWindow {
self.isHidden = false
aa.makeKeyAndVisible()
} else {
self.bringSubviewToFront(self.edoMaskView)
}
UIView.animate(withDuration: self.edoAnimationDuration, delay: 0, options: [.curveEaseOut, .beginFromCurrentState], animations: {
self.edoMaskView.alpha = 1.0
}) { (finished) in
}
}
/// 隐藏遮罩层
func hideEdoBackground(_ popupSWindow: EdoPopupSWindow) {
if self.edoReferenceCount > 1 {
return
}
UIView.animate(withDuration: self.edoAnimationDuration, delay: 0, options: [.curveEaseIn, .beginFromCurrentState], animations: {
self.edoMaskView.alpha = 0.0
}) { (finished) in
if self == popupSWindow.attachView() {
popupSWindow.isHidden = true
} else if self.isKind(of: UIWindow.self) {
self.isHidden = true
}
self.edoReferenceCount -= 1
}
}
}