mirror of https://github.com/xaoxuu/ProHUD
update
This commit is contained in:
parent
d6e8ae791f
commit
b8763cd45f
|
@ -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 {
|
|
||||||
// hud.show(t)
|
|
||||||
// }
|
|
||||||
// t.didTapped { [weak t] in
|
|
||||||
// hud.show(a)
|
|
||||||
// t?.remove()
|
|
||||||
// }
|
|
||||||
|
|
||||||
// a.didMinimize {
|
let a = ProHUD.show(alert : .loading, title: "正在加载", message: "请稍候片刻")
|
||||||
// ProHUD.show(toast: .loading, title: "正在加载", message: "哈哈").didTapped {
|
a.didMinimize {
|
||||||
// ProHUD.show(toast: .loading, title: "正在加载", message: "哈克里斯蒂娜疯狂拉升的反馈老实交代分开就撒开了击快乐圣诞哈克里斯蒂娜疯狂拉升的反馈老实交代分开就撒开了击快乐圣诞")
|
hud.show(t)
|
||||||
// }
|
}
|
||||||
// }
|
t.didTapped { [weak t] in
|
||||||
|
t?.remove()
|
||||||
|
let a2 = ProHUD.show(alert: .loading, title: "正在加载", message: "马上就要成功了")
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now()+1) {
|
||||||
|
a2.updateContent(scene: .error, title: "加载失败", message: "点击充实")
|
||||||
|
a2.addAction(style: .default, title: "重新加载") { [weak a2] in
|
||||||
|
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) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,49 +263,58 @@ 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.height会变成0
|
window.rootViewController = toast // 此时toast.view.frame.size会自动更新为window.frame.size
|
||||||
toast.view.frame.size.height = height
|
// 根据在屏幕中的顺序,确定y坐标
|
||||||
|
if toasts.contains(toast) == false {
|
||||||
|
toasts.append(toast)
|
||||||
|
}
|
||||||
updateToastsLayout()
|
updateToastsLayout()
|
||||||
|
if isNew {
|
||||||
window.transform = .init(translationX: 0, y: -window.frame.maxY)
|
window.transform = .init(translationX: 0, y: -window.frame.maxY)
|
||||||
UIView.animateForToast {
|
UIView.animateForToast {
|
||||||
window.transform = .identity
|
window.transform = .identity
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
toast.view.layoutIfNeeded()
|
||||||
|
}
|
||||||
return toast
|
return toast
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,32 +381,43 @@ 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() {
|
||||||
|
func f() {
|
||||||
|
let top = Inspire.shared.screen.updatedSafeAreaInsets.top
|
||||||
for (i, e) in toasts.enumerated() {
|
for (i, e) in toasts.enumerated() {
|
||||||
let config = toastConfig
|
let config = toastConfig
|
||||||
if let window = e.window {
|
if let window = e.window {
|
||||||
var frame = window.frame
|
var y = window.frame.origin.y
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
if isPortrait {
|
if isPortrait {
|
||||||
frame.origin.y = Inspire.shared.screen.updatedSafeAreaInsets.top
|
y = top
|
||||||
} else {
|
} else {
|
||||||
frame.origin.y = config.margin
|
y = config.margin
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let lastY = toasts[i-1].window?.frame.maxY ?? .zero
|
let lastY = toasts[i-1].window?.frame.maxY ?? .zero
|
||||||
frame.origin.y = lastY + config.margin
|
y = lastY + config.margin
|
||||||
}
|
}
|
||||||
UIView.animateForToast(animations: {
|
UIView.animateForToast {
|
||||||
e.window?.frame = frame
|
e.window?.frame.origin.y = y
|
||||||
}) { (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 {
|
||||||
|
|
Loading…
Reference in New Issue