This commit is contained in:
xaoxuu 2019-08-01 20:22:57 +08:00
parent d6e8ae791f
commit b8763cd45f
6 changed files with 118 additions and 67 deletions

View File

@ -41,26 +41,34 @@ class ViewController: UIViewController {
// //
// }.addAction(style: .cancel, title: "", action: nil).didDisappear { // }.addAction(style: .cancel, title: "", action: nil).didDisappear {
// debugPrint("didDisappear") // debugPrint("didDisappear")
// }.addAction(style: .cancel, title: nil) {
//
// } // }
// let t = ProHUD.Toast(scene: .loading, title: "", message: "") let t = ProHUD.Toast(scene: .loading, title: "正在加载", message: "请稍候片刻")
// let a = ProHUD.show(alert: .loading, title: "", message: "")
// a.didMinimize { let a = ProHUD.show(alert : .loading, title: "正在加载", message: "请稍候片刻")
// hud.show(t) a.didMinimize {
// } hud.show(t)
// t.didTapped { [weak t] in }
// hud.show(a) t.didTapped { [weak t] in
// t?.remove() t?.remove()
// } let a2 = ProHUD.show(alert: .loading, title: "正在加载", message: "马上就要成功了")
DispatchQueue.main.asyncAfter(deadline: .now()+1) {
// a.didMinimize { a2.updateContent(scene: .error, title: "加载失败", message: "点击充实")
// ProHUD.show(toast: .loading, title: "", message: "").didTapped { a2.addAction(style: .default, title: "重新加载") { [weak a2] in
// ProHUD.show(toast: .loading, title: "", message: "") a2?.updateContent(scene: .success, title: "加载成功", message: "马上就要成功了")
// } a2?.updateAction(index: 0, style: .default, title: "OK", action: { [weak a2] in
// } a2?.remove()
}).removeAction(index: 1).removeAction(index: 1)
}.addAction(style: .destructive, title: "终止", action: nil).addAction(style: .cancel, title: "取消", action: nil)
}
}
ProHUD.show(toast: .loading, title: "正在加载", message: "拉升的反馈老实交代分开就撒开了击快乐圣反馈老实交代分开就撒开了击快乐圣") // ProHUD.show(toast: .loading, title: "", message: "")
// ProHUD.show(toast: .loading, title: "", message: "") // ProHUD.show(toast: .loading, title: "", message: "")
DispatchQueue.main.asyncAfter(deadline: .now()+1) { DispatchQueue.main.asyncAfter(deadline: .now()+1) {

View File

@ -68,7 +68,7 @@ public extension ProHUD {
timeout = 2 timeout = 2
} }
willLayout() willLayoutSubviews()
} }
@ -105,7 +105,7 @@ public extension ProHUD {
/// - Parameter timeout: /// - Parameter timeout:
@discardableResult public func timeout(_ timeout: TimeInterval?) -> Alert { @discardableResult public func timeout(_ timeout: TimeInterval?) -> Alert {
self.timeout = timeout self.timeout = timeout
willLayout() willLayoutSubviews()
return self return self
} }
@ -132,6 +132,7 @@ public extension ProHUD {
self?.remove() self?.remove()
} }
} }
willLayoutSubviews()
return self return self
} }
@ -213,15 +214,16 @@ public extension ProHUD {
} }
fileprivate extension ProHUD.Alert { fileprivate extension ProHUD.Alert {
func willLayout() { func willLayoutSubviews() {
willLayout?.cancel() willLayout?.cancel()
timeoutBlock?.cancel()
showNavButtonsBlock?.cancel()
willLayout = DispatchWorkItem(block: { [weak self] in willLayout = DispatchWorkItem(block: { [weak self] in
if let a = self { if let a = self {
// //
alertConfig.loadSubviews(a) alertConfig.loadSubviews(a)
alertConfig.updateFrame(a) alertConfig.updateFrame(a)
// //
a.timeoutBlock?.cancel()
if let t = a.timeout, t > 0 { if let t = a.timeout, t > 0 {
a.timeoutBlock = DispatchWorkItem(block: { [weak self] in a.timeoutBlock = DispatchWorkItem(block: { [weak self] in
self?.remove() self?.remove()
@ -232,7 +234,6 @@ fileprivate extension ProHUD.Alert {
} }
// //
if alertConfig.minimizeTimeout > 0 && self?.actionStack.superview == nil { if alertConfig.minimizeTimeout > 0 && self?.actionStack.superview == nil {
a.showNavButtonsBlock?.cancel()
a.showNavButtonsBlock = DispatchWorkItem(block: { [weak self] in a.showNavButtonsBlock = DispatchWorkItem(block: { [weak self] in
if let s = self { if let s = self {
alertConfig.showNavButtons(s) alertConfig.showNavButtons(s)
@ -339,8 +340,7 @@ public extension ProHUD {
} }
// MARK: AlertHUD private func // MARK: AlertHUD private func
internal extension ProHUD {
fileprivate extension ProHUD {
func updateAlertsLayout() { func updateAlertsLayout() {
for (i, a) in alerts.reversed().enumerated() { for (i, a) in alerts.reversed().enumerated() {
@ -353,6 +353,8 @@ fileprivate extension ProHUD {
} }
} }
} }
}
fileprivate extension ProHUD {
func getAlertWindow(_ vc: UIViewController) -> UIWindow { func getAlertWindow(_ vc: UIViewController) -> UIWindow {
if let w = alertWindow { if let w = alertWindow {

View File

@ -10,6 +10,29 @@ import UIKit
public extension ProHUD { public extension ProHUD {
class ToastWindow: UIWindow {
var deviceOrientationDidChangeCallback: (() -> Void)?
public override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func deviceOrientationDidChange(_ notification: Notification){
DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
self.deviceOrientationDidChangeCallback?()
}
}
}
class StackContainer: UIStackView { class StackContainer: UIStackView {

View File

@ -10,7 +10,7 @@ import UIKit
internal let hud = ProHUD.shared internal let hud = ProHUD.shared
public class ProHUD: NSObject { public class ProHUD {
public static let shared = ProHUD() public static let shared = ProHUD()
@ -19,18 +19,14 @@ public class ProHUD: NSObject {
internal var alertWindow: UIWindow? internal var alertWindow: UIWindow?
deinit {
debugPrint(self, "deinit")
}
} }
internal extension ProHUD { internal extension ProHUD {
class var bundle: Bundle { static var bundle: Bundle {
var b = Bundle.init(for: ProHUD.self) var b = Bundle.init(for: ProHUD.Alert.self)
let p = b.path(forResource: "ProHUD", ofType: "bundle") let p = b.path(forResource: "ProHUD", ofType: "bundle")
if let bb = Bundle.init(path: p ?? "") { if let bb = Bundle.init(path: p ?? "") {
b = bb b = bb
@ -38,7 +34,7 @@ internal extension ProHUD {
return b return b
} }
class func image(named: String) -> UIImage? { static func image(named: String) -> UIImage? {
return UIImage.init(named: named, in: bundle, compatibleWith: nil) return UIImage.init(named: named, in: bundle, compatibleWith: nil)
} }

View File

@ -84,6 +84,7 @@ public extension ProHUD.Configuration {
mk.top.equalToSuperview().offset(config.padding) mk.top.equalToSuperview().offset(config.padding)
mk.leading.equalToSuperview().offset(config.padding) mk.leading.equalToSuperview().offset(config.padding)
mk.bottom.lessThanOrEqualToSuperview().offset(-config.padding) mk.bottom.lessThanOrEqualToSuperview().offset(-config.padding)
mk.width.height.equalTo(config.iconSize)
} }
vc.titleLabel.snp.makeConstraints { (mk) in vc.titleLabel.snp.makeConstraints { (mk) in
mk.top.equalToSuperview().offset(config.padding) mk.top.equalToSuperview().offset(config.padding)

View File

@ -59,6 +59,7 @@ public extension ProHUD {
/// ///
public var vm = ViewModel() public var vm = ViewModel()
public var removable = true public var removable = true
internal var tapCallback: (() -> Void)? internal var tapCallback: (() -> Void)?
@ -262,48 +263,57 @@ fileprivate extension ProHUD.Toast {
// MARK: - AlertHUD public func // MARK: - AlertHUD public func
public extension ProHUD { public extension ProHUD {
@discardableResult @discardableResult
func show(_ toast: Toast) -> Toast { func show(_ toast: Toast) -> Toast {
let config = toastConfig let config = toastConfig
let isNew: Bool
if toast.window == nil { if toast.window == nil {
let width = CGFloat.minimum(UIScreen.main.bounds.width - 2*config.margin, config.maxWidth) let w = ToastWindow(frame: .zero)
let w = UIWindow(frame: .init(x: (UIScreen.main.bounds.width - width) / 2, y: config.margin, width: width, height: 400))
toast.window = w toast.window = w
w.windowLevel = UIWindow.Level(5000) w.windowLevel = UIWindow.Level(5000)
w.backgroundColor = .clear w.backgroundColor = .clear
w.layer.shadowRadius = 8 w.layer.shadowRadius = 8
w.layer.shadowOffset = .init(width: 0, height: 5) w.layer.shadowOffset = .init(width: 0, height: 5)
w.layer.shadowOpacity = 0.2 w.layer.shadowOpacity = 0.2
w.rootViewController = toast w.isHidden = false
isNew = true
} else {
isNew = false
} }
let window = toast.window! let window = toast.window!
window.isHidden = false
toasts.append(toast)
// background & frame // background & frame
toast.view.layoutIfNeeded() //
let width = CGFloat.minimum(UIScreen.main.bounds.width - 2*config.margin, config.maxWidth)
toast.view.frame.size = CGSize(width: width, height: 800)
toast.titleLabel.sizeToFit() toast.titleLabel.sizeToFit()
toast.bodyLabel.sizeToFit() toast.bodyLabel.sizeToFit()
let width = toast.view.frame.width toast.view.layoutIfNeeded()
//
var height = CGFloat(0) var height = CGFloat(0)
for v in toast.view.subviews { for v in toast.view.subviews {
height = CGFloat.maximum(v.frame.maxY, height) height = CGFloat.maximum(v.frame.maxY, height)
} }
height += config.padding height += config.padding
toast.backgroundView.frame.size = CGSize(width: width, height: height) // frame
window.frame = CGRect(x: (UIScreen.main.bounds.width - width) / 2, y: 0, width: width, height: height)
toast.backgroundView.frame.size = window.frame.size
window.insertSubview(toast.backgroundView, at: 0) window.insertSubview(toast.backgroundView, at: 0)
window.frame.size.height = height // toast.view.frame.height0 window.rootViewController = toast // toast.view.frame.sizewindow.frame.size
toast.view.frame.size.height = height // y
if toasts.contains(toast) == false {
toasts.append(toast)
}
updateToastsLayout() updateToastsLayout()
window.transform = .init(translationX: 0, y: -window.frame.maxY) if isNew {
UIView.animateForToast { window.transform = .init(translationX: 0, y: -window.frame.maxY)
window.transform = .identity UIView.animateForToast {
window.transform = .identity
}
} else {
toast.view.layoutIfNeeded()
} }
return toast return toast
} }
@ -371,33 +381,44 @@ public extension ProHUD {
// MARK: AlertHUD private func // MARK: AlertHUD private func
fileprivate extension ProHUD { fileprivate var willUpdateToastsLayout: DispatchWorkItem?
internal extension ProHUD {
func updateToastsLayout() { func updateToastsLayout() {
for (i, e) in toasts.enumerated() { func f() {
let config = toastConfig let top = Inspire.shared.screen.updatedSafeAreaInsets.top
if let window = e.window { for (i, e) in toasts.enumerated() {
var frame = window.frame let config = toastConfig
if i == 0 { if let window = e.window {
if isPortrait { var y = window.frame.origin.y
frame.origin.y = Inspire.shared.screen.updatedSafeAreaInsets.top if i == 0 {
if isPortrait {
y = top
} else {
y = config.margin
}
} else { } else {
frame.origin.y = config.margin let lastY = toasts[i-1].window?.frame.maxY ?? .zero
y = lastY + config.margin
}
UIView.animateForToast {
e.window?.frame.origin.y = y
} }
} else {
let lastY = toasts[i-1].window?.frame.maxY ?? .zero
frame.origin.y = lastY + config.margin
}
UIView.animateForToast(animations: {
e.window?.frame = frame
}) { (done) in
} }
} }
} }
willUpdateToastsLayout?.cancel()
willUpdateToastsLayout = DispatchWorkItem(block: {
f()
})
DispatchQueue.main.asyncAfter(deadline: .now()+0.001, execute: willUpdateToastsLayout!)
} }
}
internal extension ProHUD {
func removeItemFromArray(toast: Toast) { func removeItemFromArray(toast: Toast) {
if toasts.count > 1 { if toasts.count > 1 {
for (i, t) in toasts.enumerated() { for (i, t) in toasts.enumerated() {