mirror of https://github.com/xaoxuu/ProHUD
update
This commit is contained in:
parent
70a27f58f2
commit
ff9805967a
|
@ -31,7 +31,7 @@ class ViewController: UIViewController {
|
||||||
let t = ProHUD.Toast(scene: .loading, title: "正在加载", message: "请稍候片刻")
|
let t = ProHUD.Toast(scene: .loading, title: "正在加载", message: "请稍候片刻")
|
||||||
|
|
||||||
let a = ProHUD.push(alert : .loading, title: "正在加载", message: "请稍候片刻")
|
let a = ProHUD.push(alert : .loading, title: "正在加载", message: "请稍候片刻")
|
||||||
a.didMinimize {
|
a.didForceQuit {
|
||||||
hud.push(t)
|
hud.push(t)
|
||||||
}
|
}
|
||||||
t.didTapped { [weak t] in
|
t.didTapped { [weak t] in
|
||||||
|
@ -58,13 +58,21 @@ class ViewController: UIViewController {
|
||||||
a?.removeAction(index: 0).removeAction(index: 0)
|
a?.removeAction(index: 0).removeAction(index: 0)
|
||||||
a?.updateContent(scene: .loading, title: "正在删除", message: "请稍后片刻")
|
a?.updateContent(scene: .loading, title: "正在删除", message: "请稍后片刻")
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now()+1) {
|
DispatchQueue.main.asyncAfter(deadline: .now()+1) {
|
||||||
a?.updateContent(scene: .success, title: "删除成功", message: "啊哈哈哈哈").timeout(2)
|
a?.updateContent(scene: .success, title: "删除成功", message: "啊哈哈哈哈").duration(2)
|
||||||
ProHUD.show(toast: .success, title: "删除成功", message: "aaa")
|
ProHUD.push(toast: .success, title: "删除成功", message: "aaa")
|
||||||
}
|
}
|
||||||
}).addAction(style: .cancel, title: "取消", action: nil)
|
}).addAction(style: .cancel, title: "取消", action: nil)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func test(_ sender: UIButton) {
|
@IBAction func test(_ sender: UIButton) {
|
||||||
|
|
||||||
|
|
||||||
|
textUpdateAction()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func testGuard() {
|
||||||
let g = ProHUD.Guard(title: "请求权限", message: "请打开相机权限开关,否则无法进行测量。")
|
let g = ProHUD.Guard(title: "请求权限", message: "请打开相机权限开关,否则无法进行测量。")
|
||||||
|
|
||||||
g.loadTitle("呵呵")
|
g.loadTitle("呵呵")
|
||||||
|
@ -78,8 +86,18 @@ class ViewController: UIViewController {
|
||||||
g.loadButton(style: .cancel, title: "我知道了")
|
g.loadButton(style: .cancel, title: "我知道了")
|
||||||
g.push(to: self)
|
g.push(to: self)
|
||||||
debugPrint("test: ", g)
|
debugPrint("test: ", g)
|
||||||
|
}
|
||||||
|
|
||||||
|
func textUpdateAction() {
|
||||||
|
let a = ProHUD.push(alert: .confirm, title: "确认删除", message: "此操作无法撤销")
|
||||||
|
a.addAction(style: .destructive, title: "删除") {
|
||||||
|
a.removeAction(index: 0, 1).updateContent(scene: .loading, title: "正在删除", message: "请稍后片刻")
|
||||||
|
}.addAction(style: .cancel, title: "取消", action: nil)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,7 @@ fileprivate var privReloadData: (ProHUD.Alert) -> Void = {
|
||||||
isFirstLayout = false
|
isFirstLayout = false
|
||||||
}
|
}
|
||||||
let imgStr: String
|
let imgStr: String
|
||||||
switch vc.vm.scene {
|
switch vc.model.scene {
|
||||||
case .success:
|
case .success:
|
||||||
imgStr = "ProHUDSuccess"
|
imgStr = "ProHUDSuccess"
|
||||||
case .warning:
|
case .warning:
|
||||||
|
@ -148,7 +148,7 @@ fileprivate var privReloadData: (ProHUD.Alert) -> Void = {
|
||||||
default:
|
default:
|
||||||
imgStr = "ProHUDMessage"
|
imgStr = "ProHUDMessage"
|
||||||
}
|
}
|
||||||
let img = vc.vm.icon ?? ProHUD.image(named: imgStr)
|
let img = vc.model.icon ?? ProHUD.image(named: imgStr)
|
||||||
if let imgv = vc.imageView {
|
if let imgv = vc.imageView {
|
||||||
imgv.image = img
|
imgv.image = img
|
||||||
} else {
|
} else {
|
||||||
|
@ -167,7 +167,7 @@ fileprivate var privReloadData: (ProHUD.Alert) -> Void = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// text
|
// text
|
||||||
if vc.vm.title?.count ?? 0 > 0 || vc.vm.message?.count ?? 0 > 0 {
|
if vc.model.title?.count ?? 0 > 0 || vc.model.message?.count ?? 0 > 0 {
|
||||||
vc.contentStack.addArrangedSubview(vc.textStack)
|
vc.contentStack.addArrangedSubview(vc.textStack)
|
||||||
vc.textStack.snp.makeConstraints { (mk) in
|
vc.textStack.snp.makeConstraints { (mk) in
|
||||||
mk.top.greaterThanOrEqualTo(vc.contentView).offset(config.padding*1.75)
|
mk.top.greaterThanOrEqualTo(vc.contentView).offset(config.padding*1.75)
|
||||||
|
@ -175,19 +175,19 @@ fileprivate var privReloadData: (ProHUD.Alert) -> Void = {
|
||||||
mk.leading.greaterThanOrEqualTo(vc.contentView).offset(config.padding*2)
|
mk.leading.greaterThanOrEqualTo(vc.contentView).offset(config.padding*2)
|
||||||
mk.trailing.lessThanOrEqualTo(vc.contentView).offset(-config.padding*2)
|
mk.trailing.lessThanOrEqualTo(vc.contentView).offset(-config.padding*2)
|
||||||
}
|
}
|
||||||
if vc.vm.title?.count ?? 0 > 0 {
|
if vc.model.title?.count ?? 0 > 0 {
|
||||||
if let lb = vc.titleLabel {
|
if let lb = vc.titleLabel {
|
||||||
lb.text = vc.vm.title
|
lb.text = vc.model.title
|
||||||
} else {
|
} else {
|
||||||
let title = UILabel()
|
let title = UILabel()
|
||||||
title.textAlignment = .center
|
title.textAlignment = .center
|
||||||
title.numberOfLines = config.titleMaxLines
|
title.numberOfLines = config.titleMaxLines
|
||||||
title.textColor = cfg.primaryLabelColor
|
title.textColor = cfg.primaryLabelColor
|
||||||
title.text = vc.vm.title
|
title.text = vc.model.title
|
||||||
vc.textStack.addArrangedSubview(title)
|
vc.textStack.addArrangedSubview(title)
|
||||||
vc.titleLabel = title
|
vc.titleLabel = title
|
||||||
}
|
}
|
||||||
if vc.vm.message?.count ?? 0 > 0 {
|
if vc.model.message?.count ?? 0 > 0 {
|
||||||
// 有message
|
// 有message
|
||||||
vc.titleLabel?.font = config.titleFont
|
vc.titleLabel?.font = config.titleFont
|
||||||
} else {
|
} else {
|
||||||
|
@ -197,28 +197,28 @@ fileprivate var privReloadData: (ProHUD.Alert) -> Void = {
|
||||||
} else {
|
} else {
|
||||||
vc.titleLabel?.removeFromSuperview()
|
vc.titleLabel?.removeFromSuperview()
|
||||||
}
|
}
|
||||||
if vc.vm.message?.count ?? 0 > 0 {
|
if vc.model.message?.count ?? 0 > 0 {
|
||||||
if let lb = vc.messageLabel {
|
if let lb = vc.bodyLabel {
|
||||||
lb.text = vc.vm.message
|
lb.text = vc.model.message
|
||||||
} else {
|
} else {
|
||||||
let body = UILabel()
|
let body = UILabel()
|
||||||
body.textAlignment = .center
|
body.textAlignment = .center
|
||||||
body.font = config.bodyFont
|
body.font = config.bodyFont
|
||||||
body.numberOfLines = config.bodyMaxLines
|
body.numberOfLines = config.bodyMaxLines
|
||||||
body.textColor = cfg.secondaryLabelColor
|
body.textColor = cfg.secondaryLabelColor
|
||||||
body.text = vc.vm.message
|
body.text = vc.model.message
|
||||||
vc.textStack.addArrangedSubview(body)
|
vc.textStack.addArrangedSubview(body)
|
||||||
vc.messageLabel = body
|
vc.bodyLabel = body
|
||||||
}
|
}
|
||||||
if vc.vm.title?.count ?? 0 > 0 {
|
if vc.model.title?.count ?? 0 > 0 {
|
||||||
// 有title
|
// 有title
|
||||||
vc.messageLabel?.font = config.bodyFont
|
vc.bodyLabel?.font = config.bodyFont
|
||||||
} else {
|
} else {
|
||||||
// 没有title
|
// 没有title
|
||||||
vc.messageLabel?.font = config.boldTextFont
|
vc.bodyLabel?.font = config.boldTextFont
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vc.messageLabel?.removeFromSuperview()
|
vc.bodyLabel?.removeFromSuperview()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vc.textStack.removeFromSuperview()
|
vc.textStack.removeFromSuperview()
|
||||||
|
@ -297,7 +297,7 @@ fileprivate var privLoadForceQuitButton: (ProHUD.Alert) -> Void = {
|
||||||
}
|
}
|
||||||
vc.addTouchUpAction(for: btn) { [weak vc] in
|
vc.addTouchUpAction(for: btn) { [weak vc] in
|
||||||
debug("点击了隐藏")
|
debug("点击了隐藏")
|
||||||
vc?.minimizeCallback?()
|
vc?.model.forceQuitCallback?()
|
||||||
vc?.pop()
|
vc?.pop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,27 +12,34 @@ import SnapKit
|
||||||
public extension ProHUD {
|
public extension ProHUD {
|
||||||
class Alert: HUDController {
|
class Alert: HUDController {
|
||||||
|
|
||||||
/// 内容容器
|
/// 内容视图
|
||||||
public var contentView = BlurView()
|
public var contentView = BlurView()
|
||||||
|
|
||||||
/// 正文(包括icon、textStack、actionStack)
|
/// 内容容器(包括icon、textStack、actionStack)
|
||||||
internal var contentStack: StackContainer = {
|
public var contentStack: StackContainer = {
|
||||||
let stack = StackContainer()
|
let stack = StackContainer()
|
||||||
stack.spacing = cfg.alert.margin
|
stack.spacing = cfg.alert.margin
|
||||||
return stack
|
return stack
|
||||||
}()
|
}()
|
||||||
|
|
||||||
/// 文本区域
|
/// 文本区容器
|
||||||
internal var textStack: StackContainer = {
|
public var textStack: StackContainer = {
|
||||||
let stack = StackContainer()
|
let stack = StackContainer()
|
||||||
stack.spacing = cfg.alert.margin
|
stack.spacing = cfg.alert.margin
|
||||||
return stack
|
return stack
|
||||||
}()
|
}()
|
||||||
internal var imageView: UIImageView?
|
|
||||||
internal var titleLabel: UILabel?
|
/// 图片
|
||||||
internal var messageLabel: UILabel?
|
public var imageView: UIImageView?
|
||||||
|
|
||||||
|
/// 标题
|
||||||
|
public var titleLabel: UILabel?
|
||||||
|
|
||||||
|
/// 正文
|
||||||
|
public var bodyLabel: UILabel?
|
||||||
|
|
||||||
/// 操作区域
|
/// 操作区域
|
||||||
internal var actionStack: StackContainer = {
|
public var actionStack: StackContainer = {
|
||||||
let stack = StackContainer()
|
let stack = StackContainer()
|
||||||
stack.alignment = .fill
|
stack.alignment = .fill
|
||||||
stack.spacing = cfg.alert.margin
|
stack.spacing = cfg.alert.margin
|
||||||
|
@ -40,12 +47,8 @@ public extension ProHUD {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
/// 视图模型
|
/// 视图模型
|
||||||
public var vm = ViewModel()
|
public var model = ViewModel()
|
||||||
|
|
||||||
/// 显示顶部按钮(最小化)
|
|
||||||
internal var showNavButtonsBlock: DispatchWorkItem?
|
|
||||||
|
|
||||||
internal var minimizeCallback: (() -> Void)?
|
|
||||||
|
|
||||||
// MARK: 生命周期
|
// MARK: 生命周期
|
||||||
|
|
||||||
|
@ -57,15 +60,15 @@ public extension ProHUD {
|
||||||
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) {
|
||||||
self.init()
|
self.init()
|
||||||
view.tintColor = cfg.alert.tintColor
|
view.tintColor = cfg.alert.tintColor
|
||||||
vm.scene = scene
|
model.scene = scene
|
||||||
vm.title = title
|
model.title = title
|
||||||
vm.message = message
|
model.message = message
|
||||||
vm.icon = icon
|
model.icon = icon
|
||||||
switch scene {
|
switch scene {
|
||||||
case .loading:
|
case .loading:
|
||||||
timeout = nil
|
model.duration = nil
|
||||||
default:
|
default:
|
||||||
timeout = 2
|
model.duration = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
willLayoutSubviews()
|
willLayoutSubviews()
|
||||||
|
@ -78,172 +81,312 @@ public extension ProHUD {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// 移除
|
|
||||||
public func pop() {
|
|
||||||
let window = hud.getAlertWindow(self)
|
|
||||||
hud.removeItemFromArray(alert: self)
|
|
||||||
UIView.animateForAlertBuildOut(animations: {
|
|
||||||
self.view.alpha = 0
|
|
||||||
self.view.transform = .init(scaleX: 1.08, y: 1.08)
|
|
||||||
}) { (done) in
|
|
||||||
self.view.removeFromSuperview()
|
|
||||||
self.removeFromParent()
|
|
||||||
}
|
|
||||||
// hide window
|
|
||||||
let count = hud.alerts.count
|
|
||||||
if count == 0 && hud.alertWindow != nil {
|
|
||||||
UIView.animateForAlertBuildOut(animations: {
|
|
||||||
window.backgroundColor = window.backgroundColor?.withAlphaComponent(0)
|
|
||||||
}) { (done) in
|
|
||||||
hud.alertWindow = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// MARK: 设置函数
|
|
||||||
|
|
||||||
/// 设置超时时间
|
|
||||||
/// - Parameter timeout: 超时时间
|
|
||||||
@discardableResult public func timeout(_ timeout: TimeInterval?) -> Alert {
|
|
||||||
self.timeout = timeout
|
|
||||||
willLayoutSubviews()
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 添加按钮
|
|
||||||
/// - Parameter style: 样式
|
|
||||||
/// - Parameter text: 标题
|
|
||||||
/// - Parameter action: 事件
|
|
||||||
@discardableResult public func addAction(style: UIAlertAction.Style, title: String?, action: (() -> Void)?) -> Alert {
|
|
||||||
if let btn = privAddButton(custom: Button.actionButton(title: title), action: action) as? Button {
|
|
||||||
btn.update(style: style)
|
|
||||||
}
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 添加按钮
|
|
||||||
/// - Parameter button: 按钮
|
|
||||||
/// - Parameter action: 事件
|
|
||||||
@discardableResult public func addAction(custom button: UIButton, action: (() -> Void)?) -> Alert {
|
|
||||||
privAddButton(custom: button, action: action)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 最小化事件
|
|
||||||
/// - Parameter callback: 事件回调
|
|
||||||
@discardableResult public func didMinimize(_ callback: (() -> Void)?) -> Alert {
|
|
||||||
minimizeCallback = callback
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 消失事件
|
|
||||||
/// - Parameter callback: 事件回调
|
|
||||||
@discardableResult public func didDisappear(_ callback: (() -> Void)?) -> Alert {
|
|
||||||
disappearCallback = callback
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 更新标题
|
|
||||||
/// - Parameter title: 标题
|
|
||||||
@discardableResult public func updateContent(scene: Scene, title: String? = nil, message: String? = nil, icon: UIImage? = nil) -> Alert {
|
|
||||||
vm.title = title
|
|
||||||
vm.message = message
|
|
||||||
vm.scene = scene
|
|
||||||
vm.icon = icon
|
|
||||||
cfg.alert.reloadData(self)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// 更新按钮
|
|
||||||
/// - Parameter index: 索引
|
|
||||||
/// - Parameter style: 样式
|
|
||||||
/// - Parameter title: 标题
|
|
||||||
/// - Parameter action: 事件
|
|
||||||
@discardableResult public func updateAction(index: Int, style: UIAlertAction.Style, title: String?, action: (() -> Void)?) -> Alert {
|
|
||||||
return updateAction(index: index, button: { (btn) in
|
|
||||||
btn.setTitle(title, for: .normal)
|
|
||||||
if let b = btn as? Button {
|
|
||||||
b.update(style: style)
|
|
||||||
}
|
|
||||||
btn.layoutIfNeeded()
|
|
||||||
}, action: action)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@discardableResult public func updateAction(index: Int, button: (UIButton) -> Void, action: (() -> Void)? = nil) -> 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
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult public func removeAction(index: Int) -> Alert {
|
|
||||||
if index < 0 {
|
|
||||||
for view in self.actionStack.arrangedSubviews {
|
|
||||||
if let btn = view as? UIButton {
|
|
||||||
btn.removeFromSuperview()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if index < self.actionStack.arrangedSubviews.count, let btn = self.actionStack.arrangedSubviews[index] as? UIButton {
|
|
||||||
btn.removeFromSuperview()
|
|
||||||
}
|
|
||||||
if self.actionStack.arrangedSubviews.count == 0 {
|
|
||||||
self.actionStack.removeFromSuperview()
|
|
||||||
}
|
|
||||||
willLayoutSubviews()
|
|
||||||
UIView.animateForAlert {
|
|
||||||
self.view.layoutIfNeeded()
|
|
||||||
}
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - 实例函数
|
||||||
|
|
||||||
|
public extension ProHUD.Alert {
|
||||||
|
|
||||||
|
// MARK: 生命周期函数
|
||||||
|
|
||||||
|
/// 推入屏幕
|
||||||
|
@discardableResult func push() -> ProHUD.Alert {
|
||||||
|
return ProHUD.push(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 弹出屏幕
|
||||||
|
func pop() {
|
||||||
|
let window = hud.getAlertWindow(self)
|
||||||
|
hud.removeItemFromArray(alert: self)
|
||||||
|
UIView.animateForAlertBuildOut(animations: {
|
||||||
|
self.view.alpha = 0
|
||||||
|
self.view.transform = .init(scaleX: 1.08, y: 1.08)
|
||||||
|
}) { (done) in
|
||||||
|
self.view.removeFromSuperview()
|
||||||
|
self.removeFromParent()
|
||||||
|
}
|
||||||
|
// hide window
|
||||||
|
let count = hud.alerts.count
|
||||||
|
if count == 0 && hud.alertWindow != nil {
|
||||||
|
UIView.animateForAlertBuildOut(animations: {
|
||||||
|
window.backgroundColor = window.backgroundColor?.withAlphaComponent(0)
|
||||||
|
}) { (done) in
|
||||||
|
hud.alertWindow = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: 设置函数
|
||||||
|
|
||||||
|
/// 设置超时时间
|
||||||
|
/// - Parameter duration: 超时时间
|
||||||
|
@discardableResult func duration(_ duration: TimeInterval?) -> ProHUD.Alert {
|
||||||
|
model.duration = duration
|
||||||
|
willLayoutSubviews()
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 添加按钮
|
||||||
|
/// - Parameter style: 样式
|
||||||
|
/// - Parameter text: 标题
|
||||||
|
/// - Parameter action: 事件
|
||||||
|
@discardableResult func addAction(style: UIAlertAction.Style, title: String?, action: (() -> Void)?) -> ProHUD.Alert {
|
||||||
|
if let btn = privAddButton(custom: Button.actionButton(title: title), action: action) as? Button {
|
||||||
|
btn.update(style: style)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 添加按钮
|
||||||
|
/// - Parameter button: 按钮
|
||||||
|
/// - Parameter action: 事件
|
||||||
|
@discardableResult func addAction(custom button: UIButton, action: (() -> Void)?) -> ProHUD.Alert {
|
||||||
|
privAddButton(custom: button, action: action)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 最小化事件
|
||||||
|
/// - Parameter callback: 事件回调
|
||||||
|
@discardableResult func didForceQuit(_ callback: (() -> Void)?) -> ProHUD.Alert {
|
||||||
|
model.forceQuitCallback = callback
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 消失事件
|
||||||
|
/// - Parameter callback: 事件回调
|
||||||
|
@discardableResult func didDisappear(_ callback: (() -> Void)?) -> ProHUD.Alert {
|
||||||
|
disappearCallback = callback
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 更新标题
|
||||||
|
/// - Parameter title: 标题
|
||||||
|
@discardableResult func updateContent(scene: Scene, title: String? = nil, message: String? = nil, icon: UIImage? = nil) -> ProHUD.Alert {
|
||||||
|
model.title = title
|
||||||
|
model.message = message
|
||||||
|
model.scene = scene
|
||||||
|
model.icon = icon
|
||||||
|
cfg.alert.reloadData(self)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 更新按钮
|
||||||
|
/// - Parameter index: 索引
|
||||||
|
/// - Parameter style: 样式
|
||||||
|
/// - Parameter title: 标题
|
||||||
|
/// - Parameter action: 事件
|
||||||
|
@discardableResult func updateAction(index: Int, style: UIAlertAction.Style, title: String?, action: (() -> Void)?) -> ProHUD.Alert {
|
||||||
|
return updateAction(index: index, button: { (btn) in
|
||||||
|
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 updateAction(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 removeAction(index: Int...) -> ProHUD.Alert {
|
||||||
|
for (i, idx) in index.enumerated() {
|
||||||
|
privRemoveAction(index: idx-i)
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - 实例函数
|
||||||
|
|
||||||
|
public extension ProHUD {
|
||||||
|
|
||||||
|
/// 推入屏幕
|
||||||
|
/// - Parameter alert: 实例
|
||||||
|
@discardableResult func push(_ alert: Alert) -> Alert {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 推入屏幕
|
||||||
|
/// - Parameter alert: 场景
|
||||||
|
/// - Parameter title: 标题
|
||||||
|
/// - Parameter message: 正文
|
||||||
|
/// - Parameter icon: 图标
|
||||||
|
@discardableResult func push(alert scene: Alert.Scene, title: String? = nil, message: String? = nil, icon: UIImage? = nil) -> Alert {
|
||||||
|
return push(Alert(scene: scene, title: title, message: message, icon: icon))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取指定的实例
|
||||||
|
/// - Parameter identifier: 指定实例的标识
|
||||||
|
func alerts(identifier: String?) -> [Alert] {
|
||||||
|
var aa = [Alert]()
|
||||||
|
for a in alerts {
|
||||||
|
if a.identifier == identifier {
|
||||||
|
aa.append(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aa
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 弹出屏幕
|
||||||
|
/// - 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, icon: UIImage? = nil) -> Alert {
|
||||||
|
return shared.push(alert: alert, title: title, message: message, icon: icon)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 获取指定的实例
|
||||||
|
/// - Parameter identifier: 指定实例的标识
|
||||||
|
class func alert(identifier: String?) -> [Alert] {
|
||||||
|
return shared.alerts(identifier: identifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 弹出屏幕
|
||||||
|
/// - Parameter alert: 实例
|
||||||
|
class func pop(alert: Alert) {
|
||||||
|
shared.pop(alert: alert)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 弹出实例
|
||||||
|
/// - Parameter identifier: 指定实例的标识
|
||||||
|
class func pop(alert identifier: String?) {
|
||||||
|
shared.pop(alert: identifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - 私有
|
||||||
|
|
||||||
fileprivate extension ProHUD.Alert {
|
fileprivate extension ProHUD.Alert {
|
||||||
|
|
||||||
|
/// 移除按钮
|
||||||
|
/// - Parameter index: 索引
|
||||||
|
@discardableResult func privRemoveAction(index: Int) -> ProHUD.Alert {
|
||||||
|
if index < 0 {
|
||||||
|
for view in self.actionStack.arrangedSubviews {
|
||||||
|
if let btn = view as? UIButton {
|
||||||
|
btn.removeFromSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if index < self.actionStack.arrangedSubviews.count, let btn = self.actionStack.arrangedSubviews[index] as? UIButton {
|
||||||
|
btn.removeFromSuperview()
|
||||||
|
}
|
||||||
|
if self.actionStack.arrangedSubviews.count == 0 {
|
||||||
|
self.actionStack.removeFromSuperview()
|
||||||
|
}
|
||||||
|
willLayoutSubviews()
|
||||||
|
UIView.animateForAlert {
|
||||||
|
self.view.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
func willLayoutSubviews() {
|
func willLayoutSubviews() {
|
||||||
willLayout?.cancel()
|
willLayout?.cancel()
|
||||||
timeoutBlock?.cancel()
|
model.durationBlock?.cancel()
|
||||||
showNavButtonsBlock?.cancel()
|
model.forceQuitTimerBlock?.cancel()
|
||||||
willLayout = DispatchWorkItem(block: { [weak self] in
|
willLayout = DispatchWorkItem(block: { [weak self] in
|
||||||
if let a = self {
|
if let a = self {
|
||||||
// 布局
|
// 布局
|
||||||
cfg.alert.loadSubviews(a)
|
cfg.alert.loadSubviews(a)
|
||||||
cfg.alert.reloadData(a)
|
cfg.alert.reloadData(a)
|
||||||
// 超时
|
// 超时
|
||||||
if let t = a.timeout, t > 0 {
|
if let t = a.model.duration, t > 0 {
|
||||||
a.timeoutBlock = DispatchWorkItem(block: { [weak self] in
|
a.model.durationBlock = DispatchWorkItem(block: { [weak self] in
|
||||||
self?.pop()
|
self?.pop()
|
||||||
})
|
})
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now()+t, execute: a.timeoutBlock!)
|
DispatchQueue.main.asyncAfter(deadline: .now()+t, execute: a.model.durationBlock!)
|
||||||
} else {
|
} else {
|
||||||
a.timeoutBlock = nil
|
a.model.durationBlock = nil
|
||||||
}
|
}
|
||||||
// 顶部按钮
|
// 强制退出按钮
|
||||||
if cfg.alert.forceQuitTimer > 0 && self?.actionStack.superview == nil {
|
if cfg.alert.forceQuitTimer > 0 && self?.actionStack.superview == nil {
|
||||||
a.showNavButtonsBlock = DispatchWorkItem(block: { [weak self] in
|
a.model.forceQuitTimerBlock = DispatchWorkItem(block: { [weak self] in
|
||||||
if let s = self {
|
if let s = self {
|
||||||
cfg.alert.loadForceQuitButton(s)
|
cfg.alert.loadForceQuitButton(s)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now()+cfg.alert.forceQuitTimer, execute: a.showNavButtonsBlock!)
|
DispatchQueue.main.asyncAfter(deadline: .now()+cfg.alert.forceQuitTimer, execute: a.model.forceQuitTimerBlock!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now()+0.001, execute: willLayout!)
|
DispatchQueue.main.asyncAfter(deadline: .now()+0.001, execute: willLayout!)
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult private func privAddButton(custom button: UIButton, action: (() -> Void)?) -> UIButton {
|
@discardableResult func privAddButton(custom button: UIButton, action: (() -> Void)?) -> UIButton {
|
||||||
timeout = nil
|
model.duration = nil
|
||||||
if actionStack.superview == nil {
|
if actionStack.superview == nil {
|
||||||
contentStack.addArrangedSubview(actionStack)
|
contentStack.addArrangedSubview(actionStack)
|
||||||
}
|
}
|
||||||
|
@ -266,95 +409,6 @@ fileprivate extension ProHUD.Alert {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - AlertHUD public func
|
|
||||||
|
|
||||||
public extension ProHUD {
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
func push(_ alert: Alert) -> Alert {
|
|
||||||
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 timeout
|
|
||||||
if let _ = alert.timeout, alert.timeoutBlock == nil {
|
|
||||||
alert.timeout(alert.timeout)
|
|
||||||
}
|
|
||||||
return alert
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
func push(alert: Alert.Scene, title: String? = nil, message: String? = nil, icon: UIImage? = nil) -> Alert {
|
|
||||||
return push(Alert(scene: alert, title: title, message: message, icon: icon))
|
|
||||||
}
|
|
||||||
|
|
||||||
func alerts(identifier: String?) -> [Alert] {
|
|
||||||
var aa = [Alert]()
|
|
||||||
for a in alerts {
|
|
||||||
if a.identifier == identifier {
|
|
||||||
aa.append(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return aa
|
|
||||||
}
|
|
||||||
|
|
||||||
func pop(alert: Alert) {
|
|
||||||
for a in alerts {
|
|
||||||
if a == alert {
|
|
||||||
a.pop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func pop(alert identifier: String?) {
|
|
||||||
for a in alerts {
|
|
||||||
if a.identifier == identifier {
|
|
||||||
a.pop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// MARK: AlertHUD public class func
|
|
||||||
|
|
||||||
public extension ProHUD {
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
class func push(_ alert: Alert) -> Alert {
|
|
||||||
return shared.push(alert)
|
|
||||||
}
|
|
||||||
|
|
||||||
@discardableResult
|
|
||||||
class func push(alert: Alert.Scene, title: String? = nil, message: String? = nil, icon: UIImage? = nil) -> Alert {
|
|
||||||
return shared.push(alert: alert, title: title, message: message, icon: icon)
|
|
||||||
}
|
|
||||||
|
|
||||||
class func alert(identifier: String?) -> [Alert] {
|
|
||||||
return shared.alerts(identifier: identifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
class func pop(alert: Alert) {
|
|
||||||
shared.pop(alert: alert)
|
|
||||||
}
|
|
||||||
|
|
||||||
class func pop(alert identifier: String?) {
|
|
||||||
shared.pop(alert: identifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: AlertHUD private func
|
|
||||||
internal extension ProHUD {
|
internal extension ProHUD {
|
||||||
|
|
||||||
func updateAlertsLayout() {
|
func updateAlertsLayout() {
|
||||||
|
@ -369,6 +423,7 @@ internal extension ProHUD {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate extension ProHUD {
|
fileprivate extension ProHUD {
|
||||||
|
|
||||||
func getAlertWindow(_ vc: UIViewController) -> UIWindow {
|
func getAlertWindow(_ vc: UIViewController) -> UIWindow {
|
||||||
|
|
|
@ -66,6 +66,18 @@ public extension ProHUD.Alert {
|
||||||
/// 图标
|
/// 图标
|
||||||
public var icon: UIImage?
|
public var icon: UIImage?
|
||||||
|
|
||||||
|
/// 持续时间
|
||||||
|
internal var duration: TimeInterval?
|
||||||
|
|
||||||
|
/// 持续时间
|
||||||
|
internal var durationBlock: DispatchWorkItem?
|
||||||
|
|
||||||
|
/// 显示顶部按钮(最小化)
|
||||||
|
internal var forceQuitTimerBlock: DispatchWorkItem?
|
||||||
|
|
||||||
|
/// 强制退出代码
|
||||||
|
internal var forceQuitCallback: (() -> Void)?
|
||||||
|
|
||||||
public init(title: String? = nil, message: String? = nil, icon: UIImage? = nil) {
|
public init(title: String? = nil, message: String? = nil, icon: UIImage? = nil) {
|
||||||
self.title = title
|
self.title = title
|
||||||
self.message = message
|
self.message = message
|
||||||
|
|
|
@ -9,12 +9,13 @@
|
||||||
import SnapKit
|
import SnapKit
|
||||||
|
|
||||||
public extension ProHUD {
|
public extension ProHUD {
|
||||||
|
|
||||||
class Guard: HUDController {
|
class Guard: HUDController {
|
||||||
|
|
||||||
/// 内容容器
|
/// 内容视图
|
||||||
public var contentView = BlurView()
|
public var contentView = BlurView()
|
||||||
|
|
||||||
/// 内容容器(包括textStack、actionStack)
|
/// 内容容器(包括textStack、actionStack,可以自己插入需要的控件)
|
||||||
public var contentStack: StackContainer = {
|
public var contentStack: StackContainer = {
|
||||||
let stack = StackContainer()
|
let stack = StackContainer()
|
||||||
stack.spacing = cfg.guard.padding + cfg.guard.margin
|
stack.spacing = cfg.guard.padding + cfg.guard.margin
|
||||||
|
@ -22,7 +23,7 @@ public extension ProHUD {
|
||||||
return stack
|
return stack
|
||||||
}()
|
}()
|
||||||
|
|
||||||
/// 文本区域
|
/// 文本区容器
|
||||||
public var textStack: StackContainer = {
|
public var textStack: StackContainer = {
|
||||||
let stack = StackContainer()
|
let stack = StackContainer()
|
||||||
stack.spacing = cfg.guard.margin
|
stack.spacing = cfg.guard.margin
|
||||||
|
@ -30,10 +31,7 @@ public extension ProHUD {
|
||||||
return stack
|
return stack
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// public var titleLabel: UILabel?
|
/// 操作区容器
|
||||||
// public var bodyLabel: UILabel?
|
|
||||||
|
|
||||||
/// 操作区域
|
|
||||||
public var actionStack: StackContainer = {
|
public var actionStack: StackContainer = {
|
||||||
let stack = StackContainer()
|
let stack = StackContainer()
|
||||||
stack.alignment = .fill
|
stack.alignment = .fill
|
||||||
|
@ -47,6 +45,7 @@ public extension ProHUD {
|
||||||
private let tag = Int(23905340)
|
private let tag = Int(23905340)
|
||||||
|
|
||||||
private var displaying = false
|
private var displaying = false
|
||||||
|
|
||||||
// MARK: 生命周期
|
// MARK: 生命周期
|
||||||
|
|
||||||
/// 实例化
|
/// 实例化
|
||||||
|
@ -56,7 +55,7 @@ public extension ProHUD {
|
||||||
/// - Parameter icon: 图标
|
/// - Parameter icon: 图标
|
||||||
public convenience init(title: String? = nil, message: String? = nil) {
|
public convenience init(title: String? = nil, message: String? = nil) {
|
||||||
self.init()
|
self.init()
|
||||||
// view = View()
|
|
||||||
view.tintColor = cfg.guard.tintColor
|
view.tintColor = cfg.guard.tintColor
|
||||||
if let _ = title {
|
if let _ = title {
|
||||||
loadTitle(title)
|
loadTitle(title)
|
||||||
|
@ -84,48 +83,58 @@ public extension ProHUD {
|
||||||
debug(self, "deinit")
|
debug(self, "deinit")
|
||||||
}
|
}
|
||||||
|
|
||||||
public func push(to viewController: UIViewController? = nil) {
|
|
||||||
if let vc = viewController {
|
|
||||||
view.layoutIfNeeded()
|
|
||||||
vc.addChild(self)
|
|
||||||
vc.view.addSubview(view)
|
|
||||||
view.isUserInteractionEnabled = true
|
|
||||||
view.snp.makeConstraints { (mk) in
|
|
||||||
mk.edges.equalToSuperview()
|
|
||||||
}
|
|
||||||
if displaying == false {
|
|
||||||
translateOut()
|
|
||||||
}
|
|
||||||
displaying = true
|
|
||||||
UIView.animateForGuard {
|
|
||||||
self.translateIn()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - 实例函数
|
||||||
|
|
||||||
|
public extension ProHUD.Guard {
|
||||||
|
|
||||||
|
// MARK: 生命周期函数
|
||||||
|
|
||||||
|
/// 推入某个视图控制器
|
||||||
|
/// - Parameter viewController: 视图控制器
|
||||||
|
func push(to viewController: UIViewController? = nil) {
|
||||||
|
if let vc = viewController {
|
||||||
|
view.layoutIfNeeded()
|
||||||
|
vc.addChild(self)
|
||||||
|
vc.view.addSubview(view)
|
||||||
|
view.isUserInteractionEnabled = true
|
||||||
|
view.snp.makeConstraints { (mk) in
|
||||||
|
mk.edges.equalToSuperview()
|
||||||
|
}
|
||||||
|
if displaying == false {
|
||||||
|
translateOut()
|
||||||
|
}
|
||||||
|
displaying = true
|
||||||
|
UIView.animateForGuard {
|
||||||
|
self.translateIn()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func pop() {
|
}
|
||||||
if displaying {
|
|
||||||
debug("pop")
|
/// 从父视图控制器弹出
|
||||||
displaying = false
|
func pop() {
|
||||||
view.isUserInteractionEnabled = false
|
if displaying {
|
||||||
self.removeFromParent()
|
debug("pop")
|
||||||
UIView.animateForGuard(animations: {
|
displaying = false
|
||||||
self.translateOut()
|
view.isUserInteractionEnabled = false
|
||||||
}) { (done) in
|
self.removeFromParent()
|
||||||
if self.displaying == false {
|
UIView.animateForGuard(animations: {
|
||||||
self.view.removeFromSuperview()
|
self.translateOut()
|
||||||
}
|
}) { (done) in
|
||||||
|
if self.displaying == false {
|
||||||
|
self.view.removeFromSuperview()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public extension ProHUD.Guard {
|
/// 加载一个标题
|
||||||
|
/// - Parameter text: 文本
|
||||||
@discardableResult
|
@discardableResult func loadTitle(_ text: String?) -> UILabel {
|
||||||
func loadTitle(_ text: String?) -> UILabel {
|
|
||||||
let lb = UILabel()
|
let lb = UILabel()
|
||||||
lb.font = cfg.guard.titleFont
|
lb.font = cfg.guard.titleFont
|
||||||
lb.textColor = cfg.primaryLabelColor
|
lb.textColor = cfg.primaryLabelColor
|
||||||
|
@ -144,8 +153,9 @@ public extension ProHUD.Guard {
|
||||||
return lb
|
return lb
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult
|
/// 加载一段正文
|
||||||
func loadBody(_ text: String?) -> UILabel {
|
/// - Parameter text: 文本
|
||||||
|
@discardableResult func loadBody(_ text: String?) -> UILabel {
|
||||||
let lb = UILabel()
|
let lb = UILabel()
|
||||||
lb.font = cfg.guard.bodyFont
|
lb.font = cfg.guard.bodyFont
|
||||||
lb.textColor = cfg.secondaryLabelColor
|
lb.textColor = cfg.secondaryLabelColor
|
||||||
|
@ -156,8 +166,11 @@ public extension ProHUD.Guard {
|
||||||
return lb
|
return lb
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult
|
/// 加载一个按钮
|
||||||
func loadButton(style: UIAlertAction.Style, title: String?, action: (() -> Void)? = nil) -> UIButton {
|
/// - Parameter style: 样式
|
||||||
|
/// - Parameter title: 标题
|
||||||
|
/// - Parameter action: 事件
|
||||||
|
@discardableResult func loadButton(style: UIAlertAction.Style, title: String?, action: (() -> Void)? = nil) -> UIButton {
|
||||||
let btn = Button.actionButton(title: title)
|
let btn = Button.actionButton(title: title)
|
||||||
btn.titleLabel?.font = cfg.guard.buttonFont
|
btn.titleLabel?.font = cfg.guard.buttonFont
|
||||||
if actionStack.superview == nil {
|
if actionStack.superview == nil {
|
||||||
|
|
|
@ -14,11 +14,6 @@ public class HUDController: UIViewController {
|
||||||
|
|
||||||
internal var willLayout: DispatchWorkItem?
|
internal var willLayout: DispatchWorkItem?
|
||||||
|
|
||||||
/// 超时(自动消失)时间
|
|
||||||
internal var timeout: TimeInterval?
|
|
||||||
|
|
||||||
internal var timeoutBlock: DispatchWorkItem?
|
|
||||||
|
|
||||||
/// 消失回调
|
/// 消失回调
|
||||||
internal var disappearCallback: (() -> Void)?
|
internal var disappearCallback: (() -> Void)?
|
||||||
internal var buttonEvents = [UIButton:() -> Void]()
|
internal var buttonEvents = [UIButton:() -> Void]()
|
||||||
|
|
|
@ -77,10 +77,10 @@ fileprivate var privReloadData: (ProHUD.Toast) -> Void = {
|
||||||
return { (vc) in
|
return { (vc) in
|
||||||
debug(vc, "reloadData")
|
debug(vc, "reloadData")
|
||||||
let config = cfg.toast
|
let config = cfg.toast
|
||||||
let scene = vc.vm.scene
|
let scene = vc.model.scene
|
||||||
// 设置数据
|
// 设置数据
|
||||||
let imgStr: String
|
let imgStr: String
|
||||||
switch vc.vm.scene {
|
switch vc.model.scene {
|
||||||
case .success:
|
case .success:
|
||||||
imgStr = "ProHUDSuccess"
|
imgStr = "ProHUDSuccess"
|
||||||
case .warning:
|
case .warning:
|
||||||
|
@ -96,12 +96,12 @@ fileprivate var privReloadData: (ProHUD.Toast) -> Void = {
|
||||||
default:
|
default:
|
||||||
imgStr = "ProHUDMessage"
|
imgStr = "ProHUDMessage"
|
||||||
}
|
}
|
||||||
let img = vc.vm.icon ?? ProHUD.image(named: imgStr)
|
let img = vc.model.icon ?? ProHUD.image(named: imgStr)
|
||||||
vc.imageView.image = img
|
vc.imageView.image = img
|
||||||
vc.titleLabel.textColor = cfg.primaryLabelColor
|
vc.titleLabel.textColor = cfg.primaryLabelColor
|
||||||
vc.titleLabel.text = vc.vm.title
|
vc.titleLabel.text = vc.model.title
|
||||||
vc.bodyLabel.textColor = cfg.secondaryLabelColor
|
vc.bodyLabel.textColor = cfg.secondaryLabelColor
|
||||||
vc.bodyLabel.text = vc.vm.message
|
vc.bodyLabel.text = vc.model.message
|
||||||
|
|
||||||
// 更新布局
|
// 更新布局
|
||||||
vc.imageView.snp.makeConstraints { (mk) in
|
vc.imageView.snp.makeConstraints { (mk) in
|
||||||
|
|
|
@ -15,14 +15,14 @@ public extension ProHUD {
|
||||||
public var window: UIWindow?
|
public var window: UIWindow?
|
||||||
|
|
||||||
/// 图标
|
/// 图标
|
||||||
internal lazy var imageView: UIImageView = {
|
public lazy var imageView: UIImageView = {
|
||||||
let imgv = UIImageView()
|
let imgv = UIImageView()
|
||||||
imgv.contentMode = .scaleAspectFit
|
imgv.contentMode = .scaleAspectFit
|
||||||
return imgv
|
return imgv
|
||||||
}()
|
}()
|
||||||
|
|
||||||
/// 标题
|
/// 标题
|
||||||
internal lazy var titleLabel: UILabel = {
|
public lazy var titleLabel: UILabel = {
|
||||||
let lb = UILabel()
|
let lb = UILabel()
|
||||||
lb.textColor = cfg.primaryLabelColor
|
lb.textColor = cfg.primaryLabelColor
|
||||||
lb.font = cfg.toast.titleFont
|
lb.font = cfg.toast.titleFont
|
||||||
|
@ -32,7 +32,7 @@ public extension ProHUD {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
/// 正文
|
/// 正文
|
||||||
internal lazy var bodyLabel: UILabel = {
|
public lazy var bodyLabel: UILabel = {
|
||||||
let lb = UILabel()
|
let lb = UILabel()
|
||||||
lb.textColor = cfg.secondaryLabelColor
|
lb.textColor = cfg.secondaryLabelColor
|
||||||
lb.font = cfg.toast.bodyFont
|
lb.font = cfg.toast.bodyFont
|
||||||
|
@ -42,7 +42,7 @@ public extension ProHUD {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
/// 背景层
|
/// 背景层
|
||||||
var backgroundView: UIVisualEffectView = {
|
public var backgroundView: UIVisualEffectView = {
|
||||||
let vev = UIVisualEffectView()
|
let vev = UIVisualEffectView()
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
vev.effect = UIBlurEffect.init(style: .systemMaterial)
|
vev.effect = UIBlurEffect.init(style: .systemMaterial)
|
||||||
|
@ -55,12 +55,7 @@ public extension ProHUD {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
/// 视图模型
|
/// 视图模型
|
||||||
public var vm = ViewModel()
|
public var model = ViewModel()
|
||||||
|
|
||||||
|
|
||||||
public var removable = true
|
|
||||||
|
|
||||||
internal var tapCallback: (() -> Void)?
|
|
||||||
|
|
||||||
// MARK: 生命周期
|
// MARK: 生命周期
|
||||||
|
|
||||||
|
@ -72,15 +67,15 @@ public extension ProHUD {
|
||||||
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) {
|
||||||
self.init()
|
self.init()
|
||||||
|
|
||||||
vm.scene = scene
|
model.scene = scene
|
||||||
vm.title = title
|
model.title = title
|
||||||
vm.message = message
|
model.message = message
|
||||||
vm.icon = icon
|
model.icon = icon
|
||||||
switch scene {
|
switch scene {
|
||||||
case .loading:
|
case .loading:
|
||||||
timeout = nil
|
model.duration = nil
|
||||||
default:
|
default:
|
||||||
timeout = 2
|
model.duration = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
// 布局
|
// 布局
|
||||||
|
@ -101,88 +96,103 @@ public extension ProHUD {
|
||||||
disappearCallback?()
|
disappearCallback?()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// 移除
|
}
|
||||||
public func pop() {
|
|
||||||
hud.removeItemFromArray(toast: self)
|
// MARK: - 实例函数
|
||||||
UIView.animateForToast(animations: {
|
|
||||||
let frame = self.window?.frame ?? .zero
|
public extension ProHUD.Toast {
|
||||||
self.window?.transform = .init(translationX: 0, y: -200-frame.maxY)
|
|
||||||
}) { (done) in
|
// MARK: 生命周期函数
|
||||||
self.view.removeFromSuperview()
|
|
||||||
self.removeFromParent()
|
/// 推入屏幕
|
||||||
self.window = nil
|
func push() {
|
||||||
}
|
ProHUD.push(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 弹出屏幕
|
||||||
|
func pop() {
|
||||||
|
hud.removeItemFromArray(toast: self)
|
||||||
|
UIView.animateForToast(animations: {
|
||||||
|
let frame = self.window?.frame ?? .zero
|
||||||
|
self.window?.transform = .init(translationX: 0, y: -200-frame.maxY)
|
||||||
|
}) { (done) in
|
||||||
|
self.view.removeFromSuperview()
|
||||||
|
self.removeFromParent()
|
||||||
|
self.window = nil
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@discardableResult
|
// MARK: 设置函数
|
||||||
func update(title: String?) -> Toast {
|
|
||||||
vm.title = title
|
/// 设置持续时间
|
||||||
titleLabel.text = title
|
/// - Parameter duration: 持续时间
|
||||||
return self
|
@discardableResult func duration(_ duration: TimeInterval?) -> ProHUD.Toast {
|
||||||
|
model.duration = duration
|
||||||
|
// 持续时间
|
||||||
|
model.durationBlock?.cancel()
|
||||||
|
if let t = duration, t > 0 {
|
||||||
|
model.durationBlock = DispatchWorkItem(block: { [weak self] in
|
||||||
|
self?.pop()
|
||||||
|
})
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now()+t, execute: model.durationBlock!)
|
||||||
|
} else {
|
||||||
|
model.durationBlock = nil
|
||||||
}
|
}
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
@discardableResult
|
/// 点击事件
|
||||||
func update(message: String?) -> Toast {
|
/// - Parameter callback: 事件回调
|
||||||
vm.message = message
|
@discardableResult func didTapped(_ callback: (() -> Void)?) -> ProHUD.Toast {
|
||||||
bodyLabel.text = message
|
model.tapCallback = callback
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult
|
/// 消失事件
|
||||||
func update(icon: UIImage?) -> Toast {
|
/// - Parameter callback: 事件回调
|
||||||
vm.icon = icon
|
@discardableResult func didDisappear(_ callback: (() -> Void)?) -> ProHUD.Toast {
|
||||||
imageView.image = icon
|
disappearCallback = callback
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 更新
|
||||||
|
/// - Parameter scene: 场景
|
||||||
|
/// - Parameter title: 标题
|
||||||
|
/// - Parameter message: 内容
|
||||||
|
/// - Parameter icon: 图标
|
||||||
|
@discardableResult func update(scene: Scene, title: String? = nil, message: String? = nil, icon: UIImage? = nil) -> ProHUD.Toast {
|
||||||
|
model.scene = scene
|
||||||
|
model.title = title
|
||||||
|
model.message = message
|
||||||
|
model.icon = icon
|
||||||
|
cfg.toast.reloadData(self)
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: 设置函数
|
/// 更新标题
|
||||||
|
/// - Parameter title: 标题
|
||||||
/// 设置超时时间
|
@discardableResult func update(title: String?) -> ProHUD.Toast {
|
||||||
/// - Parameter timeout: 超时时间
|
model.title = title
|
||||||
@discardableResult public func timeout(_ timeout: TimeInterval?) -> Toast {
|
titleLabel.text = title
|
||||||
self.timeout = timeout
|
return self
|
||||||
// 超时
|
}
|
||||||
timeoutBlock?.cancel()
|
|
||||||
if let t = timeout, t > 0 {
|
|
||||||
timeoutBlock = DispatchWorkItem(block: { [weak self] in
|
|
||||||
self?.pop()
|
|
||||||
})
|
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now()+t, execute: timeoutBlock!)
|
|
||||||
} else {
|
|
||||||
timeoutBlock = nil
|
|
||||||
}
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 点击事件
|
|
||||||
/// - Parameter callback: 事件回调
|
|
||||||
@discardableResult public func didTapped(_ callback: (() -> Void)?) -> Toast {
|
|
||||||
tapCallback = callback
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 消失事件
|
|
||||||
/// - Parameter callback: 事件回调
|
|
||||||
@discardableResult public func didDisappear(_ callback: (() -> Void)?) -> Toast {
|
|
||||||
disappearCallback = callback
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 更新标题
|
|
||||||
/// - Parameter title: 标题
|
|
||||||
@discardableResult public func update(scene: Scene, title: String? = nil, message: String? = nil, icon: UIImage? = nil) -> Toast {
|
|
||||||
vm.scene = scene
|
|
||||||
vm.title = title
|
|
||||||
vm.message = message
|
|
||||||
vm.icon = icon
|
|
||||||
cfg.toast.reloadData(self)
|
|
||||||
return self
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
/// 更新文本
|
||||||
|
/// - Parameter message: 消息
|
||||||
|
@discardableResult func update(message: String?) -> ProHUD.Toast {
|
||||||
|
model.message = message
|
||||||
|
bodyLabel.text = message
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 更新图标
|
||||||
|
/// - Parameter icon: 图标
|
||||||
|
@discardableResult func update(icon: UIImage?) -> ProHUD.Toast {
|
||||||
|
model.icon = icon
|
||||||
|
imageView.image = icon
|
||||||
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -192,18 +202,18 @@ fileprivate extension ProHUD.Toast {
|
||||||
/// 点击事件
|
/// 点击事件
|
||||||
/// - Parameter sender: 手势
|
/// - Parameter sender: 手势
|
||||||
@objc func privDidTapped(_ sender: UITapGestureRecognizer) {
|
@objc func privDidTapped(_ sender: UITapGestureRecognizer) {
|
||||||
tapCallback?()
|
model.tapCallback?()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 拖拽事件
|
/// 拖拽事件
|
||||||
/// - Parameter sender: 手势
|
/// - Parameter sender: 手势
|
||||||
@objc func privDidPan(_ sender: UIPanGestureRecognizer) {
|
@objc func privDidPan(_ sender: UIPanGestureRecognizer) {
|
||||||
timeoutBlock?.cancel()
|
model.durationBlock?.cancel()
|
||||||
let point = sender.translation(in: sender.view)
|
let point = sender.translation(in: sender.view)
|
||||||
window?.transform = .init(translationX: 0, y: point.y)
|
window?.transform = .init(translationX: 0, y: point.y)
|
||||||
if sender.state == .recognized {
|
if sender.state == .recognized {
|
||||||
let v = sender.velocity(in: sender.view)
|
let v = sender.velocity(in: sender.view)
|
||||||
if removable == true && (((window?.frame.origin.y ?? 0) < 0 && v.y < 0) || v.y < -1200) {
|
if model.removable == true && (((window?.frame.origin.y ?? 0) < 0 && v.y < 0) || v.y < -1200) {
|
||||||
// 移除
|
// 移除
|
||||||
self.pop()
|
self.pop()
|
||||||
} else {
|
} else {
|
||||||
|
@ -219,11 +229,13 @@ fileprivate extension ProHUD.Toast {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: - AlertHUD public func
|
// MARK: - 实例函数
|
||||||
|
|
||||||
public extension ProHUD {
|
public extension ProHUD {
|
||||||
|
|
||||||
@discardableResult
|
/// Toast推入屏幕
|
||||||
func push(_ toast: Toast) -> Toast {
|
/// - Parameter toast: 实例
|
||||||
|
@discardableResult func push(_ toast: Toast) -> Toast {
|
||||||
let config = cfg.toast
|
let config = cfg.toast
|
||||||
let isNew: Bool
|
let isNew: Bool
|
||||||
if toast.window == nil {
|
if toast.window == nil {
|
||||||
|
@ -275,11 +287,17 @@ public extension ProHUD {
|
||||||
return toast
|
return toast
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult
|
/// Toast推入屏幕
|
||||||
func push(toast: Toast.Scene, title: String? = nil, message: String? = nil, icon: UIImage? = nil) -> Toast {
|
/// - Parameter toast: 场景
|
||||||
return push(Toast(scene: toast, title: title, message: message, icon: icon))
|
/// - Parameter title: 标题
|
||||||
|
/// - Parameter message: 内容
|
||||||
|
/// - Parameter icon: 图标
|
||||||
|
@discardableResult func push(toast scene: Toast.Scene, title: String? = nil, message: String? = nil, icon: UIImage? = nil) -> Toast {
|
||||||
|
return push(Toast(scene: scene, title: title, message: message, icon: icon))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 获取指定的toast
|
||||||
|
/// - Parameter identifier: 标识
|
||||||
func toasts(identifier: String?) -> [Toast] {
|
func toasts(identifier: String?) -> [Toast] {
|
||||||
var tt = [Toast]()
|
var tt = [Toast]()
|
||||||
for t in toasts {
|
for t in toasts {
|
||||||
|
@ -290,6 +308,8 @@ public extension ProHUD {
|
||||||
return tt
|
return tt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Toast弹出屏幕
|
||||||
|
/// - Parameter toast: 实例
|
||||||
func pop(toast: Toast) {
|
func pop(toast: Toast) {
|
||||||
for t in toasts {
|
for t in toasts {
|
||||||
if t == toast {
|
if t == toast {
|
||||||
|
@ -298,6 +318,8 @@ public extension ProHUD {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Toast弹出屏幕
|
||||||
|
/// - Parameter identifier: 需要弹出的Toast的标识
|
||||||
func pop(toast identifier: String?) {
|
func pop(toast identifier: String?) {
|
||||||
for t in toasts {
|
for t in toasts {
|
||||||
if t.identifier == identifier {
|
if t.identifier == identifier {
|
||||||
|
@ -305,38 +327,50 @@ public extension ProHUD {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: AlertHUD public class func
|
// MARK: 类函数
|
||||||
|
|
||||||
public extension ProHUD {
|
public extension ProHUD {
|
||||||
|
|
||||||
@discardableResult
|
/// Toast推入屏幕
|
||||||
class func push(_ toast: Toast) -> Toast {
|
/// - Parameter toast: 实例
|
||||||
|
@discardableResult class func push(_ toast: Toast) -> Toast {
|
||||||
return shared.push(toast)
|
return shared.push(toast)
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult
|
/// Toast推入屏幕
|
||||||
class func show(toast: Toast.Scene, title: String? = nil, message: String? = nil, icon: UIImage? = nil) -> Toast {
|
/// - Parameter toast: 场景
|
||||||
|
/// - Parameter title: 标题
|
||||||
|
/// - Parameter message: 内容
|
||||||
|
/// - Parameter icon: 图标
|
||||||
|
@discardableResult class func push(toast: Toast.Scene, title: String? = nil, message: String? = nil, icon: UIImage? = nil) -> Toast {
|
||||||
return shared.push(toast: toast, title: title, message: message, icon: icon)
|
return shared.push(toast: toast, title: title, message: message, icon: icon)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 获取指定的toast
|
||||||
|
/// - Parameter identifier: 标识
|
||||||
class func toast(identifier: String?) -> [Toast] {
|
class func toast(identifier: String?) -> [Toast] {
|
||||||
return shared.toasts(identifier: identifier)
|
return shared.toasts(identifier: identifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Toast弹出屏幕
|
||||||
|
/// - Parameter toast: 实例
|
||||||
class func pop(toast: Toast) {
|
class func pop(toast: Toast) {
|
||||||
shared.pop(toast: toast)
|
shared.pop(toast: toast)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Toast弹出屏幕
|
||||||
|
/// - Parameter identifier: 需要弹出的Toast的标识
|
||||||
class func pop(toast identifier: String?) {
|
class func pop(toast identifier: String?) {
|
||||||
shared.pop(toast: identifier)
|
shared.pop(toast: identifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: AlertHUD private func
|
// MARK: 私有
|
||||||
|
|
||||||
fileprivate var willUpdateToastsLayout: DispatchWorkItem?
|
fileprivate var willUpdateToastsLayout: DispatchWorkItem?
|
||||||
|
|
||||||
|
@ -375,7 +409,8 @@ internal extension ProHUD {
|
||||||
|
|
||||||
internal extension ProHUD {
|
internal extension ProHUD {
|
||||||
|
|
||||||
|
/// 从数组中移除
|
||||||
|
/// - Parameter toast: 实例
|
||||||
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() {
|
||||||
|
|
|
@ -45,6 +45,18 @@ public extension ProHUD.Toast {
|
||||||
/// 图标
|
/// 图标
|
||||||
public var icon: UIImage?
|
public var icon: UIImage?
|
||||||
|
|
||||||
|
/// 持续时间
|
||||||
|
internal var duration: TimeInterval?
|
||||||
|
|
||||||
|
/// 持续时间
|
||||||
|
internal var durationBlock: DispatchWorkItem?
|
||||||
|
|
||||||
|
/// 是否可以通过手势移除(向上划)
|
||||||
|
public var removable = true
|
||||||
|
|
||||||
|
/// 点击事件回调
|
||||||
|
internal var tapCallback: (() -> Void)?
|
||||||
|
|
||||||
public init(title: String? = nil, message: String? = nil, icon: UIImage? = nil) {
|
public init(title: String? = nil, message: String? = nil, icon: UIImage? = nil) {
|
||||||
self.title = title
|
self.title = title
|
||||||
self.message = message
|
self.message = message
|
||||||
|
|
Loading…
Reference in New Issue