mirror of https://github.com/xaoxuu/ProHUD
update
This commit is contained in:
parent
c165d05de4
commit
4cebb3fc72
|
@ -9,9 +9,15 @@
|
|||
import UIKit
|
||||
import SnapKit
|
||||
|
||||
public typealias Alert = ProHUD.Alert
|
||||
|
||||
public extension ProHUD {
|
||||
class Alert: HUDController {
|
||||
|
||||
internal static var alerts = [Alert]()
|
||||
|
||||
internal static var alertWindow: UIWindow?
|
||||
|
||||
/// 内容视图
|
||||
public var contentView = BlurView()
|
||||
|
||||
|
@ -57,14 +63,14 @@ public extension ProHUD {
|
|||
/// - Parameter title: 标题
|
||||
/// - Parameter message: 内容
|
||||
/// - Parameter icon: 图标
|
||||
public convenience init(scene: Scene = .default, title: String? = nil, message: String? = nil, icon: UIImage? = nil) {
|
||||
public convenience init(scene: Scene = .default, title: String? = nil, message: String? = nil, icon: UIImage? = nil, actions: ((Alert) -> Void)? = nil) {
|
||||
self.init()
|
||||
view.tintColor = cfg.alert.tintColor
|
||||
model.scene = scene
|
||||
model.title = title
|
||||
model.message = message
|
||||
model.icon = icon
|
||||
|
||||
actions?(self)
|
||||
willLayoutSubviews()
|
||||
|
||||
}
|
||||
|
@ -76,20 +82,40 @@ public extension ProHUD {
|
|||
|
||||
// MARK: - 实例函数
|
||||
|
||||
public extension ProHUD.Alert {
|
||||
public extension Alert {
|
||||
|
||||
// MARK: 生命周期函数
|
||||
|
||||
/// 推入屏幕
|
||||
@discardableResult func push() -> ProHUD.Alert {
|
||||
return ProHUD.push(self)
|
||||
@discardableResult func push() -> Alert {
|
||||
let hud = ProHUD.shared
|
||||
if Alert.alerts.contains(self) == false {
|
||||
let window = Alert.getAlertWindow(self)
|
||||
window.makeKeyAndVisible()
|
||||
window.resignKey()
|
||||
window.addSubview(view)
|
||||
view.transform = .init(scaleX: 1.2, y: 1.2)
|
||||
view.alpha = 0
|
||||
UIView.animateForAlertBuildIn {
|
||||
self.view.transform = .identity
|
||||
self.view.alpha = 1
|
||||
window.backgroundColor = window.backgroundColor?.withAlphaComponent(0.6)
|
||||
}
|
||||
Alert.alerts.append(self)
|
||||
}
|
||||
Alert.updateAlertsLayout()
|
||||
|
||||
// setup duration
|
||||
if let _ = model.duration, model.durationBlock == nil {
|
||||
duration(model.duration)
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
/// 弹出屏幕
|
||||
func pop() {
|
||||
let hud = ProHUD.shared
|
||||
let window = hud.getAlertWindow(self)
|
||||
hud.removeItemFromArray(alert: self)
|
||||
let window = Alert.getAlertWindow(self)
|
||||
Alert.removeItemFromArray(alert: self)
|
||||
UIView.animateForAlertBuildOut(animations: {
|
||||
self.view.alpha = 0
|
||||
self.view.transform = .init(scaleX: 1.08, y: 1.08)
|
||||
|
@ -98,12 +124,12 @@ public extension ProHUD.Alert {
|
|||
self.removeFromParent()
|
||||
}
|
||||
// hide window
|
||||
let count = hud.alerts.count
|
||||
if count == 0 && hud.alertWindow != nil {
|
||||
let count = Alert.alerts.count
|
||||
if count == 0 && Alert.alertWindow != nil {
|
||||
UIView.animateForAlertBuildOut(animations: {
|
||||
window.backgroundColor = window.backgroundColor?.withAlphaComponent(0)
|
||||
}) { (done) in
|
||||
hud.alertWindow = nil
|
||||
Alert.alertWindow = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,39 +140,32 @@ public extension ProHUD.Alert {
|
|||
/// 添加按钮
|
||||
/// - Parameter style: 样式
|
||||
/// - Parameter text: 标题
|
||||
/// - Parameter action: 事件
|
||||
@discardableResult func add(action style: UIAlertAction.Style, title: String?, handler: (() -> Void)?) -> ProHUD.Alert {
|
||||
if let btn = privAddButton(custom: Button.actionButton(title: title), action: handler) as? Button {
|
||||
btn.update(style: style)
|
||||
/// - Parameter handler: 事件处理
|
||||
@discardableResult func add(action style: UIAlertAction.Style, title: String?, handler: (() -> Void)?) -> UIButton {
|
||||
let btn = privAddButton(custom: Button.actionButton(title: title), action: handler)
|
||||
if let b = btn as? Button {
|
||||
b.update(style: style)
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
/// 添加按钮
|
||||
/// - Parameter button: 按钮
|
||||
/// - Parameter action: 事件
|
||||
@discardableResult func add(button: UIButton, action: (() -> Void)?) -> ProHUD.Alert {
|
||||
privAddButton(custom: button, action: action)
|
||||
return self
|
||||
return btn
|
||||
}
|
||||
|
||||
/// 最小化事件
|
||||
/// - Parameter callback: 事件回调
|
||||
@discardableResult func didForceQuit(_ callback: (() -> Void)?) -> ProHUD.Alert {
|
||||
@discardableResult func didForceQuit(_ callback: (() -> Void)?) -> Alert {
|
||||
model.forceQuitCallback = callback
|
||||
return self
|
||||
}
|
||||
|
||||
/// 消失事件
|
||||
/// - Parameter callback: 事件回调
|
||||
@discardableResult func didDisappear(_ callback: (() -> Void)?) -> ProHUD.Alert {
|
||||
@discardableResult func didDisappear(_ callback: (() -> Void)?) -> Alert {
|
||||
disappearCallback = callback
|
||||
return self
|
||||
}
|
||||
|
||||
/// 设置持续时间
|
||||
/// - Parameter duration: 持续时间
|
||||
@discardableResult func duration(_ duration: TimeInterval?) -> ProHUD.Alert {
|
||||
@discardableResult func duration(_ duration: TimeInterval?) -> Alert {
|
||||
model.setupDuration(duration: duration) { [weak self] in
|
||||
self?.pop()
|
||||
}
|
||||
|
@ -157,7 +176,7 @@ public extension ProHUD.Alert {
|
|||
/// - Parameter scene: 场景
|
||||
/// - Parameter title: 标题
|
||||
/// - Parameter message: 正文
|
||||
@discardableResult func update(scene: Scene, title: String?, message: String?) -> ProHUD.Alert {
|
||||
@discardableResult func update(scene: Scene, title: String?, message: String?) -> Alert {
|
||||
model.scene = scene
|
||||
model.title = title
|
||||
model.message = message
|
||||
|
@ -167,7 +186,7 @@ public extension ProHUD.Alert {
|
|||
|
||||
/// 更新图标
|
||||
/// - Parameter icon: 图标
|
||||
@discardableResult func update(icon: UIImage?) -> ProHUD.Alert {
|
||||
@discardableResult func update(icon: UIImage?) -> Alert {
|
||||
model.icon = icon
|
||||
cfg.alert.reloadData(self)
|
||||
imageView?.layer.removeAllAnimations()
|
||||
|
@ -179,36 +198,23 @@ public extension ProHUD.Alert {
|
|||
/// - Parameter style: 样式
|
||||
/// - Parameter title: 标题
|
||||
/// - Parameter action: 事件
|
||||
@discardableResult func update(action index: Int, style: UIAlertAction.Style, title: String?, action: (() -> Void)?) -> ProHUD.Alert {
|
||||
return update(action: index, button: { (btn) in
|
||||
@discardableResult func update(action index: Int, style: UIAlertAction.Style, title: String?, action: (() -> Void)?) -> Alert {
|
||||
if index < self.actionStack.arrangedSubviews.count, let btn = self.actionStack.arrangedSubviews[index] as? UIButton {
|
||||
btn.setTitle(title, for: .normal)
|
||||
if let b = btn as? Button {
|
||||
b.update(style: style)
|
||||
}
|
||||
btn.layoutIfNeeded()
|
||||
}, action: action)
|
||||
}
|
||||
|
||||
/// 更新按钮
|
||||
/// - Parameter index: 索引
|
||||
/// - Parameter button: 按钮
|
||||
/// - Parameter action: 事件
|
||||
@discardableResult func update(action index: Int, button: (UIButton) -> Void, action: (() -> Void)? = nil) -> ProHUD.Alert {
|
||||
if index < self.actionStack.arrangedSubviews.count, let btn = self.actionStack.arrangedSubviews[index] as? UIButton {
|
||||
button(btn)
|
||||
if let ac = action {
|
||||
addTouchUpAction(for: btn, action: ac)
|
||||
}
|
||||
}
|
||||
UIView.animateForAlert {
|
||||
self.view.layoutIfNeeded()
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
/// 移除按钮
|
||||
/// - Parameter index: 索引
|
||||
@discardableResult func remove(action index: Int...) -> ProHUD.Alert {
|
||||
@discardableResult func remove(action index: Int...) -> Alert {
|
||||
for (i, idx) in index.enumerated() {
|
||||
privRemoveAction(index: idx-i)
|
||||
}
|
||||
|
@ -218,130 +224,54 @@ public extension ProHUD.Alert {
|
|||
}
|
||||
|
||||
|
||||
// MARK: 类函数
|
||||
|
||||
// MARK: - 实例函数
|
||||
|
||||
public extension ProHUD {
|
||||
|
||||
/// 推入屏幕
|
||||
/// - Parameter alert: 实例
|
||||
@discardableResult func push(_ alert: Alert) -> Alert {
|
||||
if alerts.contains(alert) == false {
|
||||
let window = getAlertWindow(alert)
|
||||
window.makeKeyAndVisible()
|
||||
window.resignKey()
|
||||
window.addSubview(alert.view)
|
||||
alert.view.transform = .init(scaleX: 1.2, y: 1.2)
|
||||
alert.view.alpha = 0
|
||||
UIView.animateForAlertBuildIn {
|
||||
alert.view.transform = .identity
|
||||
alert.view.alpha = 1
|
||||
window.backgroundColor = window.backgroundColor?.withAlphaComponent(0.6)
|
||||
}
|
||||
alerts.append(alert)
|
||||
}
|
||||
updateAlertsLayout()
|
||||
|
||||
// setup duration
|
||||
if let _ = alert.model.duration, alert.model.durationBlock == nil {
|
||||
alert.duration(alert.model.duration)
|
||||
}
|
||||
return alert
|
||||
}
|
||||
public extension Alert {
|
||||
|
||||
/// 推入屏幕
|
||||
/// - Parameter alert: 场景
|
||||
/// - Parameter title: 标题
|
||||
/// - Parameter message: 正文
|
||||
/// - Parameter icon: 图标
|
||||
@discardableResult func push(alert scene: Alert.Scene, title: String? = nil, message: String? = nil, actions: ((Alert) -> Void)? = nil) -> Alert {
|
||||
let a = Alert(scene: scene, title: title, message: message)
|
||||
actions?(a)
|
||||
a.view.layoutIfNeeded()
|
||||
return push(a)
|
||||
/// - Parameter actions: 更多操作
|
||||
@discardableResult class func push(alert scene: Alert.Scene, title: String? = nil, message: String? = nil, actions: ((Alert) -> Void)? = nil) -> Alert {
|
||||
return Alert(scene: scene, title: title, message: message, actions: actions).push()
|
||||
}
|
||||
|
||||
/// 获取指定的实例
|
||||
/// - Parameter identifier: 指定实例的标识
|
||||
func alert(_ identifier: String?) -> Alert? {
|
||||
class func alerts(_ identifier: String?) -> [Alert] {
|
||||
var aa = [Alert]()
|
||||
for a in alerts {
|
||||
for a in Alert.alerts {
|
||||
if a.identifier == identifier {
|
||||
aa.append(a)
|
||||
}
|
||||
}
|
||||
return aa.last
|
||||
}
|
||||
|
||||
/// 弹出屏幕
|
||||
/// - Parameter alert: 实例
|
||||
func pop(_ alert: Alert) {
|
||||
for a in alerts {
|
||||
if a == alert {
|
||||
a.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 弹出实例
|
||||
/// - Parameter identifier: 指定实例的标识
|
||||
func pop(alert identifier: String?) {
|
||||
for a in alerts {
|
||||
if a.identifier == identifier {
|
||||
a.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// MARK: 类函数
|
||||
|
||||
public extension ProHUD {
|
||||
|
||||
/// 推入屏幕
|
||||
/// - Parameter alert: 实例
|
||||
@discardableResult class func push(_ alert: Alert) -> Alert {
|
||||
return shared.push(alert)
|
||||
}
|
||||
|
||||
/// 推入屏幕
|
||||
/// - Parameter alert: 场景
|
||||
/// - Parameter title: 标题
|
||||
/// - Parameter message: 正文
|
||||
/// - Parameter icon: 图标
|
||||
@discardableResult class func push(alert: Alert.Scene, title: String? = nil, message: String? = nil, actions: ((Alert) -> Void)? = nil) -> Alert {
|
||||
return shared.push(alert: alert, title: title, message: message, actions: actions)
|
||||
}
|
||||
|
||||
/// 获取指定的实例
|
||||
/// - Parameter identifier: 指定实例的标识
|
||||
class func alert(_ identifier: String?) -> Alert? {
|
||||
return shared.alert(identifier)
|
||||
return aa
|
||||
}
|
||||
|
||||
/// 弹出屏幕
|
||||
/// - Parameter alert: 实例
|
||||
class func pop(_ alert: Alert) {
|
||||
shared.pop(alert)
|
||||
alert.pop()
|
||||
}
|
||||
|
||||
/// 弹出实例
|
||||
/// 弹出屏幕
|
||||
/// - Parameter identifier: 指定实例的标识
|
||||
class func pop(alert identifier: String?) {
|
||||
shared.pop(alert: identifier)
|
||||
class func pop(_ identifier: String?) {
|
||||
for a in alerts(identifier) {
|
||||
a.pop()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - 私有
|
||||
|
||||
fileprivate extension ProHUD.Alert {
|
||||
fileprivate extension Alert {
|
||||
|
||||
/// 移除按钮
|
||||
/// - Parameter index: 索引
|
||||
@discardableResult func privRemoveAction(index: Int) -> ProHUD.Alert {
|
||||
@discardableResult func privRemoveAction(index: Int) -> Alert {
|
||||
if index < 0 {
|
||||
for view in self.actionStack.arrangedSubviews {
|
||||
if let btn = view as? UIButton {
|
||||
|
@ -401,9 +331,8 @@ fileprivate extension ProHUD.Alert {
|
|||
|
||||
}
|
||||
|
||||
internal extension ProHUD {
|
||||
|
||||
func updateAlertsLayout() {
|
||||
fileprivate extension Alert {
|
||||
class func updateAlertsLayout() {
|
||||
for (i, a) in alerts.reversed().enumerated() {
|
||||
let scale = CGFloat(pow(0.7, CGFloat(i)))
|
||||
UIView.animate(withDuration: 1.8, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0.5, options: [.allowUserInteraction, .curveEaseInOut], animations: {
|
||||
|
@ -414,11 +343,7 @@ internal extension ProHUD {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension ProHUD {
|
||||
|
||||
func getAlertWindow(_ vc: UIViewController) -> UIWindow {
|
||||
class func getAlertWindow(_ vc: UIViewController) -> UIWindow {
|
||||
if let w = alertWindow {
|
||||
return w
|
||||
}
|
||||
|
@ -430,7 +355,7 @@ fileprivate extension ProHUD {
|
|||
return w
|
||||
}
|
||||
|
||||
func removeItemFromArray(alert: Alert) {
|
||||
class func removeItemFromArray(alert: Alert) {
|
||||
if alerts.count > 1 {
|
||||
for (i, a) in alerts.enumerated() {
|
||||
if a == alert {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
public extension ProHUD.Alert {
|
||||
public extension Alert {
|
||||
enum Scene {
|
||||
/// 默认场景
|
||||
case `default`
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
internal extension ProHUD.Alert {
|
||||
internal extension Alert {
|
||||
class Button: UIButton {
|
||||
class func actionButton(title: String?) -> UIButton {
|
||||
let btn = Button(type: .system)
|
||||
|
|
|
@ -91,7 +91,7 @@ public extension Guard {
|
|||
|
||||
/// 推入某个视图控制器
|
||||
/// - Parameter viewController: 视图控制器
|
||||
func push(to viewController: UIViewController? = nil) {
|
||||
func push(to viewController: UIViewController? = nil) -> Guard {
|
||||
func f(_ vc: UIViewController) {
|
||||
view.layoutIfNeeded()
|
||||
vc.addChild(self)
|
||||
|
@ -113,25 +113,19 @@ public extension Guard {
|
|||
} else {
|
||||
debug("请传入需要push到的控制器")
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
/// 从父视图控制器弹出
|
||||
func pop(animated: Bool = true) {
|
||||
func pop() {
|
||||
if displaying {
|
||||
debug("pop")
|
||||
displaying = false
|
||||
view.isUserInteractionEnabled = false
|
||||
self.removeFromParent()
|
||||
if animated {
|
||||
UIView.animateForGuard(animations: {
|
||||
self.translateOut()
|
||||
}) { (done) in
|
||||
if self.displaying == false {
|
||||
self.view.removeFromSuperview()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
UIView.animateForGuard(animations: {
|
||||
self.translateOut()
|
||||
}) { (done) in
|
||||
if self.displaying == false {
|
||||
self.view.removeFromSuperview()
|
||||
}
|
||||
|
@ -139,6 +133,8 @@ public extension Guard {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: 设置函数
|
||||
|
||||
/// 加载一个标题
|
||||
/// - Parameter text: 文本
|
||||
@discardableResult func add(title: String?) -> UILabel {
|
||||
|
@ -231,20 +227,24 @@ public extension Guard {
|
|||
/// - Parameter message: 正文
|
||||
/// - Parameter icon: 图标
|
||||
@discardableResult class func push(to viewController: UIViewController? = nil, actions: ((Guard) -> Void)? = nil) -> Guard {
|
||||
let g = Guard(actions: actions)
|
||||
g.push(to: viewController)
|
||||
return g
|
||||
return Guard(actions: actions).push(to: viewController)
|
||||
}
|
||||
|
||||
/// 获取指定的实例
|
||||
/// - Parameter identifier: 指定实例的标识
|
||||
class func guards(_ identifier: String?, from viewController: UIViewController? = nil) -> [Guard] {
|
||||
class func guards(_ identifier: String? = nil, from viewController: UIViewController? = nil) -> [Guard] {
|
||||
var gg = [Guard]()
|
||||
if let vc = viewController ?? cfg.rootViewController {
|
||||
for child in vc.children {
|
||||
if child.isKind(of: Guard.self) {
|
||||
if let g = child as? Guard {
|
||||
gg.append(g)
|
||||
if let id = identifier {
|
||||
if g.identifier == id {
|
||||
gg.append(g)
|
||||
}
|
||||
} else {
|
||||
gg.append(g)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,6 +258,13 @@ public extension Guard {
|
|||
`guard`.pop()
|
||||
}
|
||||
|
||||
/// 弹出屏幕
|
||||
/// - Parameter identifier: 指定实例的标识
|
||||
class func pop(from viewController: UIViewController?) {
|
||||
for g in guards(from: viewController) {
|
||||
g.pop()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
internal extension ProHUD.Guard {
|
||||
internal extension Guard {
|
||||
|
||||
class Button: UIButton {
|
||||
class func actionButton(title: String?) -> Button {
|
||||
|
|
|
@ -16,12 +16,6 @@ public class ProHUD {
|
|||
return cfg
|
||||
}
|
||||
|
||||
internal var toasts = [Toast]()
|
||||
internal var alerts = [Alert]()
|
||||
|
||||
internal var alertWindow: UIWindow?
|
||||
|
||||
|
||||
}
|
||||
|
||||
// MARK: - Utilities
|
||||
|
@ -30,7 +24,7 @@ internal extension ProHUD {
|
|||
|
||||
/// 获取Bundle
|
||||
static var bundle: Bundle {
|
||||
var b = Bundle.init(for: ProHUD.Alert.self)
|
||||
var b = Bundle.init(for: Alert.self)
|
||||
let p = b.path(forResource: "ProHUD", ofType: "bundle")
|
||||
if let bb = Bundle.init(path: p ?? "") {
|
||||
b = bb
|
||||
|
|
|
@ -9,9 +9,13 @@
|
|||
import UIKit
|
||||
import Inspire
|
||||
|
||||
public typealias Toast = ProHUD.Toast
|
||||
|
||||
public extension ProHUD {
|
||||
class Toast: HUDController {
|
||||
|
||||
internal static var toasts = [Toast]()
|
||||
|
||||
public var window: UIWindow?
|
||||
|
||||
/// 图标
|
||||
|
@ -68,14 +72,14 @@ public extension ProHUD {
|
|||
/// - Parameter title: 标题
|
||||
/// - Parameter message: 内容
|
||||
/// - Parameter icon: 图标
|
||||
public convenience init(scene: Scene = .default, title: String? = nil, message: String? = nil, icon: UIImage? = nil) {
|
||||
public convenience init(scene: Scene = .default, title: String? = nil, message: String? = nil, icon: UIImage? = nil, actions: ((Toast) -> Void)? = nil) {
|
||||
self.init()
|
||||
|
||||
model.scene = scene
|
||||
model.title = title
|
||||
model.message = message
|
||||
model.icon = icon
|
||||
|
||||
actions?(self)
|
||||
// 布局
|
||||
cfg.toast.loadSubviews(self)
|
||||
cfg.toast.reloadData(self)
|
||||
|
@ -96,18 +100,66 @@ public extension ProHUD {
|
|||
|
||||
// MARK: - 实例函数
|
||||
|
||||
public extension ProHUD.Toast {
|
||||
public extension Toast {
|
||||
|
||||
// MARK: 生命周期函数
|
||||
|
||||
/// 推入屏幕
|
||||
func push() {
|
||||
ProHUD.push(self)
|
||||
@discardableResult func push() -> Toast {
|
||||
let config = cfg.toast
|
||||
let isNew: Bool
|
||||
if self.window == nil {
|
||||
let w = UIWindow(frame: .zero)
|
||||
self.window = w
|
||||
w.windowLevel = UIWindow.Level(5000)
|
||||
w.backgroundColor = .clear
|
||||
w.layer.shadowRadius = 8
|
||||
w.layer.shadowOffset = .init(width: 0, height: 5)
|
||||
w.layer.shadowOpacity = 0.2
|
||||
w.isHidden = false
|
||||
isNew = true
|
||||
} else {
|
||||
isNew = false
|
||||
}
|
||||
|
||||
let window = self.window!
|
||||
// background & frame
|
||||
// 设定正确的宽度,更新子视图
|
||||
let width = CGFloat.minimum(UIScreen.main.bounds.width - 2*config.margin, config.maxWidth)
|
||||
view.frame.size = CGSize(width: width, height: 800)
|
||||
titleLabel.sizeToFit()
|
||||
bodyLabel.sizeToFit()
|
||||
view.layoutIfNeeded()
|
||||
// 更新子视图之后获取正确的高度
|
||||
var height = CGFloat(0)
|
||||
for v in self.view.subviews {
|
||||
height = CGFloat.maximum(v.frame.maxY, height)
|
||||
}
|
||||
height += config.padding
|
||||
// 应用到frame
|
||||
window.frame = CGRect(x: (UIScreen.main.bounds.width - width) / 2, y: 0, width: width, height: height)
|
||||
backgroundView.frame.size = window.frame.size
|
||||
window.insertSubview(backgroundView, at: 0)
|
||||
window.rootViewController = self // 此时toast.view.frame.size会自动更新为window.frame.size
|
||||
// 根据在屏幕中的顺序,确定y坐标
|
||||
if Toast.toasts.contains(self) == false {
|
||||
Toast.toasts.append(self)
|
||||
}
|
||||
Toast.updateToastsLayout()
|
||||
if isNew {
|
||||
window.transform = .init(translationX: 0, y: -window.frame.maxY)
|
||||
UIView.animateForToast {
|
||||
window.transform = .identity
|
||||
}
|
||||
} else {
|
||||
view.layoutIfNeeded()
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
/// 弹出屏幕
|
||||
func pop() {
|
||||
ProHUD.shared.removeItemFromArray(toast: self)
|
||||
Toast.removeItemFromArray(toast: self)
|
||||
UIView.animateForToast(animations: {
|
||||
let frame = self.window?.frame ?? .zero
|
||||
self.window?.transform = .init(translationX: 0, y: -200-frame.maxY)
|
||||
|
@ -122,7 +174,7 @@ public extension ProHUD.Toast {
|
|||
|
||||
/// 设置持续时间
|
||||
/// - Parameter duration: 持续时间
|
||||
@discardableResult func duration(_ duration: TimeInterval?) -> ProHUD.Toast {
|
||||
@discardableResult func duration(_ duration: TimeInterval?) -> Toast {
|
||||
model.setupDuration(duration: duration) { [weak self] in
|
||||
self?.pop()
|
||||
}
|
||||
|
@ -131,14 +183,14 @@ public extension ProHUD.Toast {
|
|||
|
||||
/// 点击事件
|
||||
/// - Parameter callback: 事件回调
|
||||
@discardableResult func didTapped(_ callback: (() -> Void)?) -> ProHUD.Toast {
|
||||
@discardableResult func didTapped(_ callback: (() -> Void)?) -> Toast {
|
||||
model.tapCallback = callback
|
||||
return self
|
||||
}
|
||||
|
||||
/// 消失事件
|
||||
/// - Parameter callback: 事件回调
|
||||
@discardableResult func didDisappear(_ callback: (() -> Void)?) -> ProHUD.Toast {
|
||||
@discardableResult func didDisappear(_ callback: (() -> Void)?) -> Toast {
|
||||
disappearCallback = callback
|
||||
return self
|
||||
}
|
||||
|
@ -147,7 +199,7 @@ public extension ProHUD.Toast {
|
|||
/// - Parameter scene: 场景
|
||||
/// - Parameter title: 标题
|
||||
/// - Parameter message: 内容
|
||||
@discardableResult func update(scene: Scene, title: String?, message: String?) -> ProHUD.Toast {
|
||||
@discardableResult func update(scene: Scene, title: String?, message: String?) -> Toast {
|
||||
model.scene = scene
|
||||
model.title = title
|
||||
model.message = message
|
||||
|
@ -157,7 +209,7 @@ public extension ProHUD.Toast {
|
|||
|
||||
/// 更新标题
|
||||
/// - Parameter title: 标题
|
||||
@discardableResult func update(title: String?) -> ProHUD.Toast {
|
||||
@discardableResult func update(title: String?) -> Toast {
|
||||
model.title = title
|
||||
cfg.toast.reloadData(self)
|
||||
return self
|
||||
|
@ -165,7 +217,7 @@ public extension ProHUD.Toast {
|
|||
|
||||
/// 更新文本
|
||||
/// - Parameter message: 消息
|
||||
@discardableResult func update(message: String?) -> ProHUD.Toast {
|
||||
@discardableResult func update(message: String?) -> Toast {
|
||||
model.message = message
|
||||
cfg.toast.reloadData(self)
|
||||
return self
|
||||
|
@ -173,7 +225,7 @@ public extension ProHUD.Toast {
|
|||
|
||||
/// 更新图标
|
||||
/// - Parameter icon: 图标
|
||||
@discardableResult func update(icon: UIImage?) -> ProHUD.Toast {
|
||||
@discardableResult func update(icon: UIImage?) -> Toast {
|
||||
model.icon = icon
|
||||
cfg.toast.reloadData(self)
|
||||
return self
|
||||
|
@ -181,7 +233,53 @@ public extension ProHUD.Toast {
|
|||
|
||||
}
|
||||
|
||||
fileprivate extension ProHUD.Toast {
|
||||
|
||||
// MARK: 类函数
|
||||
|
||||
public extension Toast {
|
||||
|
||||
/// 推入屏幕
|
||||
/// - Parameter toast: 场景
|
||||
/// - Parameter title: 标题
|
||||
/// - Parameter message: 内容
|
||||
/// - Parameter actions: 更多操作
|
||||
@discardableResult class func push(toast scene: Toast.Scene, title: String? = nil, message: String? = nil, actions: ((Toast) -> Void)? = nil) -> Toast {
|
||||
return Toast(scene: scene, title: title, message: message, actions: actions).push()
|
||||
}
|
||||
|
||||
/// 获取指定的toast
|
||||
/// - Parameter identifier: 标识
|
||||
class func toasts(_ identifier: String?) -> [Toast] {
|
||||
var tt = [Toast]()
|
||||
for t in toasts {
|
||||
if t.identifier == identifier {
|
||||
tt.append(t)
|
||||
}
|
||||
}
|
||||
return tt
|
||||
}
|
||||
|
||||
/// 弹出屏幕
|
||||
/// - Parameter toast: 实例
|
||||
class func pop(_ toast: Toast) {
|
||||
toast.pop()
|
||||
}
|
||||
|
||||
/// 弹出屏幕
|
||||
/// - Parameter identifier: 指定实例的标识
|
||||
class func pop(_ identifier: String?) {
|
||||
for t in toasts(identifier) {
|
||||
t.pop()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: 私有
|
||||
|
||||
fileprivate var willUpdateToastsLayout: DispatchWorkItem?
|
||||
|
||||
fileprivate extension Toast {
|
||||
|
||||
/// 点击事件
|
||||
/// - Parameter sender: 手势
|
||||
|
@ -210,159 +308,24 @@ fileprivate extension ProHUD.Toast {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - 实例函数
|
||||
|
||||
public extension ProHUD {
|
||||
|
||||
/// Toast推入屏幕
|
||||
/// 从数组中移除
|
||||
/// - Parameter toast: 实例
|
||||
@discardableResult func push(_ toast: Toast) -> Toast {
|
||||
let config = cfg.toast
|
||||
let isNew: Bool
|
||||
if toast.window == nil {
|
||||
let w = UIWindow(frame: .zero)
|
||||
toast.window = w
|
||||
w.windowLevel = UIWindow.Level(5000)
|
||||
w.backgroundColor = .clear
|
||||
w.layer.shadowRadius = 8
|
||||
w.layer.shadowOffset = .init(width: 0, height: 5)
|
||||
w.layer.shadowOpacity = 0.2
|
||||
w.isHidden = false
|
||||
isNew = true
|
||||
class func removeItemFromArray(toast: Toast) {
|
||||
if toasts.count > 1 {
|
||||
for (i, t) in toasts.enumerated() {
|
||||
if t == toast {
|
||||
toasts.remove(at: i)
|
||||
}
|
||||
}
|
||||
updateToastsLayout()
|
||||
} else if toasts.count == 1 {
|
||||
toasts.removeAll()
|
||||
} else {
|
||||
isNew = false
|
||||
}
|
||||
|
||||
let window = toast.window!
|
||||
// background & frame
|
||||
// 设定正确的宽度,更新子视图
|
||||
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.bodyLabel.sizeToFit()
|
||||
toast.view.layoutIfNeeded()
|
||||
// 更新子视图之后获取正确的高度
|
||||
var height = CGFloat(0)
|
||||
for v in toast.view.subviews {
|
||||
height = CGFloat.maximum(v.frame.maxY, height)
|
||||
}
|
||||
height += config.padding
|
||||
// 应用到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.rootViewController = toast // 此时toast.view.frame.size会自动更新为window.frame.size
|
||||
// 根据在屏幕中的顺序,确定y坐标
|
||||
if toasts.contains(toast) == false {
|
||||
toasts.append(toast)
|
||||
}
|
||||
updateToastsLayout()
|
||||
if isNew {
|
||||
window.transform = .init(translationX: 0, y: -window.frame.maxY)
|
||||
UIView.animateForToast {
|
||||
window.transform = .identity
|
||||
}
|
||||
} else {
|
||||
toast.view.layoutIfNeeded()
|
||||
}
|
||||
return toast
|
||||
}
|
||||
|
||||
/// Toast推入屏幕
|
||||
/// - Parameter toast: 场景
|
||||
/// - Parameter title: 标题
|
||||
/// - Parameter message: 内容
|
||||
/// - Parameter icon: 图标
|
||||
@discardableResult func push(toast scene: Toast.Scene, title: String? = nil, message: String? = nil, actions: ((Toast) -> Void)? = nil) -> Toast {
|
||||
let t = Toast(scene: scene, title: title, message: message)
|
||||
actions?(t)
|
||||
t.view.layoutIfNeeded()
|
||||
return push(t)
|
||||
}
|
||||
|
||||
/// 获取指定的toast
|
||||
/// - Parameter identifier: 标识
|
||||
func toast(_ identifier: String?) -> Toast? {
|
||||
var tt = [Toast]()
|
||||
for t in toasts {
|
||||
if t.identifier == identifier {
|
||||
tt.append(t)
|
||||
}
|
||||
}
|
||||
return tt.last
|
||||
}
|
||||
|
||||
/// Toast弹出屏幕
|
||||
/// - Parameter toast: 实例
|
||||
func pop(_ toast: Toast) {
|
||||
for t in toasts {
|
||||
if t == toast {
|
||||
t.pop()
|
||||
}
|
||||
debug("漏洞:已经没有toast了")
|
||||
}
|
||||
}
|
||||
|
||||
/// Toast弹出屏幕
|
||||
/// - Parameter identifier: 需要弹出的Toast的标识
|
||||
func pop(toast identifier: String?) {
|
||||
for t in toasts {
|
||||
if t.identifier == identifier {
|
||||
t.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// MARK: 类函数
|
||||
|
||||
public extension ProHUD {
|
||||
|
||||
/// Toast推入屏幕
|
||||
/// - Parameter toast: 实例
|
||||
@discardableResult class func push(_ toast: Toast) -> Toast {
|
||||
return shared.push(toast)
|
||||
}
|
||||
|
||||
/// Toast推入屏幕
|
||||
/// - Parameter toast: 场景
|
||||
/// - Parameter title: 标题
|
||||
/// - Parameter message: 内容
|
||||
/// - Parameter icon: 图标
|
||||
@discardableResult class func push(toast: Toast.Scene, title: String? = nil, message: String? = nil, actions: ((Toast) -> Void)? = nil) -> Toast {
|
||||
return shared.push(toast: toast, title: title, message: message, actions: actions)
|
||||
}
|
||||
|
||||
/// 获取指定的toast
|
||||
/// - Parameter identifier: 标识
|
||||
class func toast(_ identifier: String?) -> Toast? {
|
||||
return shared.toast(identifier)
|
||||
}
|
||||
|
||||
/// Toast弹出屏幕
|
||||
/// - Parameter toast: 实例
|
||||
class func pop(_ toast: Toast) {
|
||||
shared.pop(toast)
|
||||
}
|
||||
|
||||
/// Toast弹出屏幕
|
||||
/// - Parameter identifier: 需要弹出的Toast的标识
|
||||
class func pop(toast identifier: String?) {
|
||||
shared.pop(toast: identifier)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: 私有
|
||||
|
||||
fileprivate var willUpdateToastsLayout: DispatchWorkItem?
|
||||
|
||||
internal extension ProHUD {
|
||||
func updateToastsLayout() {
|
||||
class func updateToastsLayout() {
|
||||
func f() {
|
||||
let top = Inspire.shared.screen.updatedSafeAreaInsets.top
|
||||
for (i, e) in toasts.enumerated() {
|
||||
|
@ -391,28 +354,6 @@ internal extension ProHUD {
|
|||
})
|
||||
DispatchQueue.main.asyncAfter(deadline: .now()+0.001, execute: willUpdateToastsLayout!)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal extension ProHUD {
|
||||
|
||||
/// 从数组中移除
|
||||
/// - Parameter toast: 实例
|
||||
func removeItemFromArray(toast: Toast) {
|
||||
if toasts.count > 1 {
|
||||
for (i, t) in toasts.enumerated() {
|
||||
if t == toast {
|
||||
toasts.remove(at: i)
|
||||
}
|
||||
}
|
||||
updateToastsLayout()
|
||||
} else if toasts.count == 1 {
|
||||
toasts.removeAll()
|
||||
} else {
|
||||
debug("漏洞:已经没有toast了")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
public extension ProHUD.Toast {
|
||||
public extension Toast {
|
||||
enum Scene {
|
||||
/// 默认场景
|
||||
case `default`
|
||||
|
|
Loading…
Reference in New Issue