diff --git a/Example/Example/Assets.xcassets/bg.imageset/Contents.json b/Example/Example/Assets.xcassets/bg.imageset/Contents.json index 2076d77..4a60f96 100644 --- a/Example/Example/Assets.xcassets/bg.imageset/Contents.json +++ b/Example/Example/Assets.xcassets/bg.imageset/Contents.json @@ -6,7 +6,7 @@ }, { "idiom" : "universal", - "filename" : "IMG_0564.PNG", + "filename" : "IMG_099256E14955-1.jpeg", "scale" : "2x" }, { diff --git a/Example/Example/Assets.xcassets/bg.imageset/IMG_0564.PNG b/Example/Example/Assets.xcassets/bg.imageset/IMG_0564.PNG deleted file mode 100644 index 930a677..0000000 Binary files a/Example/Example/Assets.xcassets/bg.imageset/IMG_0564.PNG and /dev/null differ diff --git a/Example/Example/Assets.xcassets/bg.imageset/IMG_099256E14955-1.jpeg b/Example/Example/Assets.xcassets/bg.imageset/IMG_099256E14955-1.jpeg new file mode 100644 index 0000000..1f611db Binary files /dev/null and b/Example/Example/Assets.xcassets/bg.imageset/IMG_099256E14955-1.jpeg differ diff --git a/Example/Example/Base.lproj/Main.storyboard b/Example/Example/Base.lproj/Main.storyboard index 5fb5f29..ded2e01 100644 --- a/Example/Example/Base.lproj/Main.storyboard +++ b/Example/Example/Base.lproj/Main.storyboard @@ -19,6 +19,14 @@ + diff --git a/Example/Example/ViewController.swift b/Example/Example/ViewController.swift index 2e4aa27..a29bf6e 100644 --- a/Example/Example/ViewController.swift +++ b/Example/Example/ViewController.swift @@ -17,27 +17,77 @@ class ViewController: UIViewController { ProHUD.configAlert { (alert) in - alert.minimizeTimeout = 5 + alert.minimizeTimeout = 3 } + ProHUD.configGuard { (g) in + g.tintColor = .success + } + ProHUD.configToast { (toast) in +// toast.backgroundColorForScene { (scene) -> UIColor? in +// return UIColor.yellow +// } + } } - - - override func touchesBegan(_ touches: Set, with event: UIEvent?) { + func testToast() { + 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 + t?.remove() + let a2 = ProHUD.show(alert: .loading, title: "正在加载", message: "马上就要成功了") + DispatchQueue.main.asyncAfter(deadline: .now()+1) { + let a3 = ProHUD.show(alert: .error, title: "加载失败", message: "点击充实") + a3.addAction(style: .default, title: "重新加载") { [weak a3] in + a3?.updateContent(scene: .success, title: "加载成功", message: "马上就要成功了") + a3?.updateAction(index: 0, style: .default, title: "OK", action: { [weak a2, a3] in + a2?.remove() + a3?.remove() + }).removeAction(index: 1).removeAction(index: 1) + }.addAction(style: .destructive, title: "终止", action: nil).addAction(style: .cancel, title: "取消", action: nil) + + } + + } + } + + func testDelete() { let a = ProHUD.show(alert: .delete, title: "确认删除", message: "此操作不可撤销") a.addAction(style: .destructive, title: "确认", action: { [weak a] in a?.removeAction(index: 0).removeAction(index: 0) a?.updateContent(scene: .loading, title: "正在删除", message: "请稍后片刻") DispatchQueue.main.asyncAfter(deadline: .now()+1) { a?.updateContent(scene: .success, title: "删除成功", message: "啊哈哈哈哈").timeout(2) - a?.addAction(style: .default, title: "我知道了", action: { -// a?.remove() - a?.removeAction(index: 0) - }) + ProHUD.show(toast: .success, title: "删除成功", message: "aaa") } }).addAction(style: .cancel, title: "取消", action: nil) + } + + @IBAction func test(_ sender: UIButton) { + let g = ProHUD.Guard(title: "请求权限", message: "请打开相机权限开关,否则无法进行测量。") +// g.view.tintColor = .warning +// g.loadBody(g.description) + + g.loadButton(style: .default, title: "测试弹窗", action: { [weak self] in + self?.testToast() + }) + g.loadButton(style: .destructive, title: "测试删除弹窗", action: { [weak self] in + self?.testDelete() + }) + g.loadButton(style: .cancel, title: "我知道了") + g.push(to: self) + debugPrint("test: ", g) + + } + override func touchesBegan(_ touches: Set, with event: UIEvent?) { + + + + // // ProHUD.show(alert: .loading, title: "确认删除", message: "此操作不可撤销").timeout(nil) @@ -63,28 +113,7 @@ class ViewController: UIViewController { // // } -// 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 -// t?.remove() -// let a2 = ProHUD.show(alert: .loading, title: "正在加载", message: "马上就要成功了") -// DispatchQueue.main.asyncAfter(deadline: .now()+1) { -// let a3 = ProHUD.show(alert: .error, title: "加载失败", message: "点击充实") -// a3.addAction(style: .default, title: "重新加载") { [weak a3] in -// a3?.updateContent(scene: .success, title: "加载成功", message: "马上就要成功了") -// a3?.updateAction(index: 0, style: .default, title: "OK", action: { [weak a2, a3] in -// a2?.remove() -// a3?.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: "拉升的反馈老实交代分开就撒开了击快乐圣反馈老实交代分开就撒开了击快乐圣") diff --git a/ProHUD/Alert/AlertConfig.swift b/ProHUD/Alert/AlertConfig.swift index 05fb8e5..f95a1cb 100644 --- a/ProHUD/Alert/AlertConfig.swift +++ b/ProHUD/Alert/AlertConfig.swift @@ -31,7 +31,7 @@ public extension ProHUD.Configuration { /// 标题字体 public var titleFont = UIFont.boldSystemFont(ofSize: 22) /// 标题颜色 - public var titleColor = UIColor(white: 0.2, alpha: 1) + public var titleColor = UIColorForPrimaryLabel /// 标题最多行数 public var titleMaxLines = Int(1) @@ -41,7 +41,7 @@ public extension ProHUD.Configuration { /// 正文字体 public var bodyFont = UIFont.systemFont(ofSize: 17) /// 正文颜色 - public var bodyColor = UIColor.darkGray + public var bodyColor = UIColorForSecondaryLabel /// 正文最多行数 public var bodyMaxLines = Int(5) @@ -232,7 +232,7 @@ public extension ProHUD.Configuration { lazy var showNavButtons: (ProHUD.Alert, Alert) -> Void = { return { (vc, config) in debugPrint(vc, "showNavButtons") - let btn = UIButton.minimizeButton() + let btn = ProHUD.Alert.Button.minimizeButton() let bg = ProHUD.BlurView() bg.layer.masksToBounds = true bg.layer.cornerRadius = config.cornerRadius diff --git a/ProHUD/Alert/AlertController.swift b/ProHUD/Alert/AlertController.swift index a1b9171..3f130d1 100644 --- a/ProHUD/Alert/AlertController.swift +++ b/ProHUD/Alert/AlertController.swift @@ -116,31 +116,17 @@ public extension ProHUD { /// - Parameter text: 标题 /// - Parameter action: 事件 @discardableResult public func addAction(style: UIAlertAction.Style, title: String?, action: (() -> Void)?) -> Alert { - return addAction(custom: UIButton.actionButton(style: style, title: title), action: action) + 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 { - timeout = nil - if actionStack.superview == nil { - contentStack.addArrangedSubview(actionStack) - } - self.view.layoutIfNeeded() - button.transform = .init(scaleX: 1, y: 0.001) - actionStack.addArrangedSubview(button) - UIView.animateForAlert { - button.transform = .identity - self.view.layoutIfNeeded() - } - addTouchUpAction(for: button) { [weak self] in - action?() - if button.tag == UIAlertAction.Style.cancel.rawValue { - self?.remove() - } - } - willLayoutSubviews() + @discardableResult public func addAction(custom button: UIButton, action: (() -> Void)?) -> Alert { + privAddButton(custom: button, action: action) return self } @@ -178,7 +164,9 @@ public extension ProHUD { @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) - btn.update(style: style) + if let b = btn as? Button { + b.update(style: style) + } btn.layoutIfNeeded() }, action: action) } @@ -254,6 +242,27 @@ fileprivate extension ProHUD.Alert { DispatchQueue.main.asyncAfter(deadline: .now()+0.001, execute: willLayout!) } + @discardableResult private func privAddButton(custom button: UIButton, action: (() -> Void)?) -> UIButton { + timeout = nil + if actionStack.superview == nil { + contentStack.addArrangedSubview(actionStack) + } + self.view.layoutIfNeeded() + button.transform = .init(scaleX: 1, y: 0.001) + actionStack.addArrangedSubview(button) + UIView.animateForAlert { + button.transform = .identity + self.view.layoutIfNeeded() + } + addTouchUpAction(for: button) { [weak self] in + action?() + if button.tag == UIAlertAction.Style.cancel.rawValue { + self?.remove() + } + } + willLayoutSubviews() + return button + } } diff --git a/ProHUD/Alert/AlertView.swift b/ProHUD/Alert/AlertView.swift index 99eb822..8521f4b 100644 --- a/ProHUD/Alert/AlertView.swift +++ b/ProHUD/Alert/AlertView.swift @@ -8,59 +8,48 @@ import UIKit -public extension ProHUD.Alert { - - -} - -extension UIButton { - - class func actionButton(style: UIAlertAction.Style, title: String?) -> UIButton { - let btn = UIButton(type: .system) - btn.setTitle(title, for: .normal) - btn.layer.cornerRadius = alertConfig.cornerRadius / 2 - btn.titleLabel?.font = alertConfig.buttonFont - btn.update(style: style) - return btn - } - - func update(style: UIAlertAction.Style) { - let pd = alertConfig.padding/2 - if style != .cancel { - backgroundColor = .init(white: 0, alpha: 0.04) - contentEdgeInsets = .init(top: pd*1.5, left: pd*1.5, bottom: pd*1.5, right: pd*1.5) - } else { - contentEdgeInsets = .init(top: pd*0.5, left: pd*1.5, bottom: pd*0.5, right: pd*1.5) +internal extension ProHUD.Alert { + class Button: UIButton { + class func actionButton(title: String?) -> UIButton { + let btn = Button(type: .system) + btn.setTitle(title, for: .normal) + btn.layer.cornerRadius = alertConfig.cornerRadius / 2 + btn.titleLabel?.font = alertConfig.buttonFont + return btn + } + + func update(style: UIAlertAction.Style) { + let pd = CGFloat(8) + if style != .cancel { + backgroundColor = dynamicColor.withAlphaComponent(0.04) + contentEdgeInsets = .init(top: pd*1.5, left: pd*1.5, bottom: pd*1.5, right: pd*1.5) + } else { + contentEdgeInsets = .init(top: pd*0.5, left: pd*1.5, bottom: pd*0.5, right: pd*1.5) + } + switch style { + case .default: + setTitleColor(tintColor, for: .normal) + case .destructive: + setTitleColor(.init(red: 244/255, green: 67/255, blue: 54/255, alpha: 1), for: .normal) + case .cancel: + setTitleColor(UIColorForSecondaryLabel, for: .normal) + @unknown default: + break + } + tag = style.rawValue + } + + class func minimizeButton() -> UIButton { + let btn = Button(type: .system) + let pd = alertConfig.padding/2 + btn.contentEdgeInsets = .init(top: pd*1.5, left: pd*1.5, bottom: pd*1.5, right: pd*1.5) + btn.imageEdgeInsets.right = pd*1.5 + btn.setTitle(alertConfig.minimizeTitle, for: .normal) + btn.setTitleColor(UIColor(red:1.00, green:0.55, blue:0.21, alpha:1.00), for: .normal) + btn.titleLabel?.font = alertConfig.buttonFont + return btn } - switch style { - case .default: - setTitleColor(alertConfig.tintColor, for: .normal) - case .destructive: - setTitleColor(.init(red: 244/255, green: 67/255, blue: 54/255, alpha: 1), for: .normal) - case .cancel: - setTitleColor(.darkGray, for: .normal) - @unknown default: - break - } - tag = style.rawValue - } - - class func minimizeButton() -> UIButton { - let btn = UIButton(type: .system) -// btn.contentEdgeInsets = .init(top: 8, left: 8, bottom: 8, right: 8) - let pd = alertConfig.padding/2 - btn.contentEdgeInsets = .init(top: pd*1.5, left: pd*1.5, bottom: pd*1.5, right: pd*1.5) -// btn.imageEdgeInsets.left = pd*0.75 - btn.imageEdgeInsets.right = pd*1.5 -// btn.setImage(ProHUD.image(named: "ProHUDMinimize"), for: .normal) -// btn.layer.shadowOpacity = 0.15 -// btn.layer.shadowOffset = .init(width: 0, height: 1.2) -// btn.layer.shadowRadius = 1.2 - btn.setTitle(alertConfig.minimizeTitle, for: .normal) - btn.setTitleColor(UIColor(red:1.00, green:0.55, blue:0.21, alpha:1.00), for: .normal) - btn.titleLabel?.font = alertConfig.buttonFont - return btn } } diff --git a/ProHUD/Guard/GuardConfig.swift b/ProHUD/Guard/GuardConfig.swift index a9da5ab..72e5b19 100644 --- a/ProHUD/Guard/GuardConfig.swift +++ b/ProHUD/Guard/GuardConfig.swift @@ -7,54 +7,149 @@ // import SnapKit +import Inspire public extension ProHUD.Configuration { struct Guard { + // MARK: 卡片样式 /// 最大宽度(用于优化横屏或者iPad显示) - public var maxWidth = CGFloat(556) - /// 标题字体 - public var titleFont = UIFont.boldSystemFont(ofSize: 18) - /// 正文字体 - public var bodyFont = UIFont.systemFont(ofSize: 16) - /// 标题最多行数(0代表不限制) - public var titleMaxLines = Int(0) - /// 正文最多行数(0代表不限制) - public var bodyMaxLines = Int(0) - /// 圆角半径 - public var cornerRadius = CGFloat(16) + public var cardMaxWidth = CGFloat(460) + /// 圆角半径(手机竖屏时为0) + public var cardCornerRadius = CGFloat(16) + /// 余量:元素与元素之间的距离 public var margin = CGFloat(8) - + /// 填充:元素内部控件距离元素边界的距离 public var padding = CGFloat(16) - public var iconSize = CGSize(width: 48, height: 48) + // MARK: 图标样式 + /// 颜色 + public var tintColor: UIColor? + + // MARK: 文本样式 + /// 标题字体 + public var titleFont = UIFont.boldSystemFont(ofSize: 22) + /// 标题颜色 + public var titleColor = UIColorForPrimaryLabel + + /// 正文字体 + public var bodyFont = UIFont.systemFont(ofSize: 18) + /// 正文颜色 + public var bodyColor = UIColorForSecondaryLabel + + // MARK: 按钮样式 + /// 按钮字体 + public var buttonFont = UIFont.boldSystemFont(ofSize: 18) + /// 按钮最大宽度(用于优化横屏或者iPad显示) +// public var buttonMaxWidth = CGFloat(460) + /// 按钮圆角半径 + public var buttonCornerRadius = CGFloat(12) + + lazy var loadTitleLabel: (ProHUD.Guard, Guard) -> Void = { + return { (vc, config) in + debugPrint(vc, "loadTitleLabel") + if vc.titleLabel == nil { + vc.titleLabel = UILabel() + vc.titleLabel?.font = config.titleFont + vc.titleLabel?.textColor = config.titleColor + vc.titleLabel?.numberOfLines = 0 + vc.titleLabel?.textAlignment = .justified + } + } + }() + + lazy var loadBodyLabel: (ProHUD.Guard, Guard) -> Void = { + return { (vc, config) in + debugPrint(vc, "loadBodyLabel") + if vc.bodyLabel == nil { + vc.bodyLabel = UILabel() + vc.bodyLabel?.font = config.bodyFont + vc.bodyLabel?.textColor = config.bodyColor + vc.bodyLabel?.numberOfLines = 0 + vc.titleLabel?.textAlignment = .justified + } + } + }() /// 加载视图 - lazy var loadSubviews: (ProHUD.Alert) -> Void = { - return { (vc) in + lazy var loadSubviews: (ProHUD.Guard, Guard) -> Void = { + return { (vc, config) in debugPrint(vc, "loadSubviews") + // background + vc.view.tintColor = config.tintColor + vc.view.backgroundColor = UIColor(white: 0, alpha: 0) + vc.view.addSubview(vc.contentView) + var width = UIScreen.main.bounds.width + if width > config.cardMaxWidth { + // 横屏或者iPad + width = config.cardMaxWidth + vc.contentView.layer.masksToBounds = true + vc.contentView.layer.cornerRadius = config.cardCornerRadius + } else { + vc.contentView.layer.shadowRadius = 4 + vc.contentView.layer.shadowOffset = .init(width: 0, height: 2) + vc.contentView.layer.shadowOpacity = 0.12 + } + vc.contentView.snp.makeConstraints { (mk) in + mk.centerX.equalToSuperview() + if UIDevice.current.userInterfaceIdiom == .phone { + if width == config.cardMaxWidth { + mk.bottom.equalToSuperview().offset(-Inspire.shared.screen.safeAreaInsets.bottom) + } else { + mk.bottom.equalToSuperview() + } + } else if UIDevice.current.userInterfaceIdiom == .pad { + mk.centerY.equalToSuperview() + } + mk.width.equalTo(width) + } + // stack + vc.contentView.contentView.addSubview(vc.contentStack) + vc.contentStack.snp.makeConstraints { (mk) in + mk.top.equalToSuperview().offset(config.padding + config.margin) + mk.centerX.equalToSuperview() + if width == config.cardMaxWidth { + mk.bottom.equalToSuperview().offset(-config.padding) + } else { + mk.bottom.equalToSuperview().offset(-config.margin-Inspire.shared.screen.safeAreaInsets.bottom) + } + if isPortrait { + mk.width.equalToSuperview().offset(-config.padding * 2) + } else { + mk.width.equalToSuperview().offset(-config.padding * 4) + } + } + vc.contentStack.addArrangedSubview(vc.textStack) } }() /// 更新视图 - lazy var updateFrame: (ProHUD.Alert) -> Void = { - return { (vc) in + lazy var updateFrame: (ProHUD.Guard, Guard) -> Void = { + return { (vc, config) in debugPrint(vc, "updateFrame") } }() /// 加载视图 /// - Parameter callback: 回调代码 - public mutating func loadSubviews(_ callback: @escaping (ProHUD.Alert) -> Void) { + public mutating func loadSubviews(_ callback: @escaping (ProHUD.Guard, Guard) -> Void) { loadSubviews = callback } /// 更新视图 /// - Parameter callback: 回调代码 - public mutating func updateFrame(_ callback: @escaping (ProHUD.Alert) -> Void) { + public mutating func updateFrame(_ callback: @escaping (ProHUD.Guard, Guard) -> Void) { updateFrame = callback } } } + +internal var guardConfig = ProHUD.Configuration.Guard() + +public extension ProHUD { + static func configGuard(_ config: (inout Configuration.Guard) -> Void) { + config(&guardConfig) + } +} diff --git a/ProHUD/Guard/GuardController.swift b/ProHUD/Guard/GuardController.swift index c35b70c..7e3092e 100644 --- a/ProHUD/Guard/GuardController.swift +++ b/ProHUD/Guard/GuardController.swift @@ -6,4 +6,193 @@ // Copyright © 2019 Titan Studio. All rights reserved. // -import Foundation +import SnapKit + +public extension ProHUD { + class Guard: HUDController { + + /// 内容容器 + public var contentView = BlurView() + + /// 内容容器(包括textStack、actionStack) + public var contentStack: StackContainer = { + let stack = StackContainer() + stack.spacing = guardConfig.padding + guardConfig.margin + stack.alignment = .fill + return stack + }() + + /// 文本区域 + public var textStack: StackContainer = { + let stack = StackContainer() + stack.spacing = guardConfig.margin + stack.alignment = .fill + return stack + }() + + public var titleLabel: UILabel? + public var bodyLabel: UILabel? + + /// 操作区域 + public var actionStack: StackContainer = { + let stack = StackContainer() + stack.alignment = .fill + stack.spacing = guardConfig.margin + return stack + }() + + /// 是否是强制性的(点击空白处是否可以消失) + public var force = false + + private let tag = Int(23905340) + + private var displaying = false + // MARK: 生命周期 + + /// 实例化 + /// - Parameter scene: 场景 + /// - Parameter title: 标题 + /// - Parameter message: 内容 + /// - Parameter icon: 图标 + public convenience init(title: String? = nil, message: String? = nil) { + self.init() + view = View() + view.tintColor = guardConfig.tintColor + if let _ = title { + loadTitle(title) + } + if let _ = message { + loadBody(message) + } + guardConfig.loadSubviews(self, guardConfig) +// willLayoutSubviews() + + // 点击 + let tap = UITapGestureRecognizer(target: self, action: #selector(privDidTapped(_:))) + view.addGestureRecognizer(tap) + + + } + + + public override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + + } + + deinit { + debugPrint(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() + } + } + + } + + public func pop() { + if displaying { + debugPrint("pop") + displaying = false + view.isUserInteractionEnabled = false + self.removeFromParent() + UIView.animateForGuard(animations: { + self.translateOut() + }) { (done) in + if self.displaying == false { + self.view.removeFromSuperview() + } + } + } + } + } +} + +public extension ProHUD.Guard { + + @discardableResult + func loadTitle(_ text: String?) -> UILabel { + guardConfig.loadTitleLabel(self, guardConfig) + let lb = titleLabel! + lb.text = text + if textStack.arrangedSubviews.count > 0 { + textStack.insertArrangedSubview(lb, at: 0) + } else { + textStack.addArrangedSubview(lb) + } + return lb + } + + @discardableResult + func loadBody(_ text: String?) -> UILabel { + guardConfig.loadBodyLabel(self, guardConfig) + let lb = bodyLabel! + lb.text = text + textStack.addArrangedSubview(lb) + return lb + } + + @discardableResult + func loadButton(style: UIAlertAction.Style, title: String?, action: (() -> Void)? = nil) -> UIButton { + let btn = Button.actionButton(title: title) + btn.titleLabel?.font = guardConfig.buttonFont + if actionStack.superview == nil { + contentStack.addArrangedSubview(actionStack) + } + actionStack.addArrangedSubview(btn) + btn.update(style: style) + addTouchUpAction(for: btn) { [weak self] in + action?() + if btn.tag == UIAlertAction.Style.cancel.rawValue { + self?.pop() + } + } + return btn + } + + +} + +fileprivate extension ProHUD.Guard { + + /// 点击事件 + /// - Parameter sender: 手势 + @objc func privDidTapped(_ sender: UITapGestureRecognizer) { + let point = sender.location(in: contentView) + if point.x < 0 || point.y < 0 { + if force == false { + // 点击到操作区域外部 + pop() + } + } + + } + + func translateIn() { + view.backgroundColor = UIColor(white: 0, alpha: 0.5) + contentView.transform = .identity + } + + func translateOut() { + view.backgroundColor = UIColor(white: 0, alpha: 0) + contentView.transform = .init(translationX: 0, y: view.frame.size.height - contentView.frame.minY + guardConfig.margin) + } + + + +} + diff --git a/ProHUD/Guard/GuardModel.swift b/ProHUD/Guard/GuardModel.swift index dc0b4c6..03ea03d 100644 --- a/ProHUD/Guard/GuardModel.swift +++ b/ProHUD/Guard/GuardModel.swift @@ -6,4 +6,23 @@ // Copyright © 2019 Titan Studio. All rights reserved. // -import Foundation +public extension ProHUD.Guard { + + struct ViewModel { + + /// 标题 + public var title: String? + + /// 正文 + public var message: String? + + public init(title: String? = nil, message: String? = nil, icon: UIImage? = nil) { + self.title = title + self.message = message + } + + + } + +} + diff --git a/ProHUD/Guard/GuardView.swift b/ProHUD/Guard/GuardView.swift index 9242f66..c01a46b 100644 --- a/ProHUD/Guard/GuardView.swift +++ b/ProHUD/Guard/GuardView.swift @@ -6,4 +6,69 @@ // Copyright © 2019 Titan Studio. All rights reserved. // -import Foundation +import UIKit + +internal extension ProHUD.Guard { + class View: UIView { + + override func willMove(toSuperview newSuperview: UIView?) { + if let sv = newSuperview { + for v in sv.subviews { + if let vv = v as? ProHUD.Guard.View { + if vv.tag == self.tag { + UIView.animate(withDuration: 0.38, delay: 0.1, options: .curveEaseIn, animations: { + vv.alpha = 0 + }) { (done) in + vv.removeFromSuperview() + } + } + } + } + } + } + +// override func didMoveToSuperview() { +// if let _ = superview { +// snp.makeConstraints { (mk) in +//// mk.left.right.bottom.equalToSuperview() +// mk.edges.equalToSuperview() +// } +//// push(duration: duration) +// } +// } + + } + class Button: UIButton { + class func actionButton(title: String?) -> Button { + let btn = Button(type: .system) + btn.setTitle(title, for: .normal) + btn.layer.cornerRadius = guardConfig.buttonCornerRadius + btn.titleLabel?.font = guardConfig.buttonFont + return btn + } + + func update(style: UIAlertAction.Style) { + let pd = CGFloat(8) + if style != .cancel { + contentEdgeInsets = .init(top: pd*1.5+2, left: pd*1.5, bottom: pd*1.5+2, right: pd*1.5) + } else { + contentEdgeInsets = .init(top: pd*1+2, left: pd*1.5, bottom: pd*1+2, right: pd*1.5) + } + switch style { + case .default: + backgroundColor = tintColor + setTitleColor(.white, for: .normal) + case .destructive: + backgroundColor = .init(red: 244/255, green: 67/255, blue: 54/255, alpha: 1) + setTitleColor(.white, for: .normal) + case .cancel: + setTitleColor(UIColorForSecondaryLabel, for: .normal) + @unknown default: + break + } + tag = style.rawValue + } + + } +} + diff --git a/ProHUD/HUDView.swift b/ProHUD/HUDView.swift index a11b37e..dbdb20c 100644 --- a/ProHUD/HUDView.swift +++ b/ProHUD/HUDView.swift @@ -55,8 +55,15 @@ public extension ProHUD { init() { - super.init(effect: UIBlurEffect(style: .light)) - backgroundColor = UIColor.init(white: 1, alpha: 0.66) + + if #available(iOS 13.0, *) { + super.init(effect: UIBlurEffect(style: .systemMaterial)) +// backgroundColor = UIColor.init(white: 1, alpha: 0.3) + } else { + super.init(effect: UIBlurEffect(style: .extraLight)) + backgroundColor = UIColor.init(white: 1, alpha: 0.66) + } + } required init?(coder: NSCoder) { @@ -96,4 +103,11 @@ internal extension UIView { animateEaseOut(duration: 1, delay: 0, animations: animations, completion: completion) } + class func animateForGuard(animations: @escaping () -> Void) { + animateForGuard(animations: animations, completion: nil) + } + + class func animateForGuard(animations: @escaping () -> Void, completion: ((Bool) -> Void)? = nil) { + animateEaseOut(duration: 0.6, delay: 0, animations: animations, completion: completion) + } } diff --git a/ProHUD/ProHUD.swift b/ProHUD/ProHUD.swift index ebbc856..ccc657f 100644 --- a/ProHUD/ProHUD.swift +++ b/ProHUD/ProHUD.swift @@ -48,3 +48,56 @@ internal var isPortrait: Bool { return false } } + + +internal var dynamicColor: UIColor { + if #available(iOS 13.0, *) { + let color = UIColor { (traitCollection: UITraitCollection) -> UIColor in + if traitCollection.userInterfaceStyle == .dark { + return .white + } else { + return .black + } + } + return color + } else { + // Fallback on earlier versions + } + return .init(white: 0.2, alpha: 1) +} + + + +internal var UIColorForPrimaryLabel: UIColor { + return dynamicColor.withAlphaComponent(0.75) +} +internal var UIColorForSecondaryLabel: UIColor { + return dynamicColor.withAlphaComponent(0.6) +} + +internal extension UIColor { + + var dynamicColor: UIColor { + if #available(iOS 13.0, *) { + let color = UIColor { (traitCollection: UITraitCollection) -> UIColor in + if traitCollection.userInterfaceStyle == .dark { + return .white + } else { + return .black + } + } + return color + } else { + // Fallback on earlier versions + } + return .init(white: 0.2, alpha: 1) + } + + var dynamicPrimaryLabelColor: UIColor { + return dynamicColor.withAlphaComponent(0.75) + } + var dynamicSecondaryLabelColor: UIColor { + return dynamicColor.withAlphaComponent(0.6) + } + +} diff --git a/ProHUD/Toast/ToastConfig.swift b/ProHUD/Toast/ToastConfig.swift index 26288b9..41f62c9 100644 --- a/ProHUD/Toast/ToastConfig.swift +++ b/ProHUD/Toast/ToastConfig.swift @@ -29,10 +29,12 @@ public extension ProHUD.Configuration { public var iconSize = CGSize(width: 48, height: 48) + public var tintColor: UIColor? /// 加载视图 lazy var loadSubviews: (ProHUD.Toast) -> Void = { return { (vc) in debugPrint(vc, "loadSubviews") + vc.view.tintColor = toastConfig.tintColor vc.view.addSubview(vc.titleLabel) vc.view.addSubview(vc.bodyLabel) vc.view.addSubview(vc.imageView) @@ -64,11 +66,10 @@ public extension ProHUD.Configuration { } let img = vc.vm.icon ?? ProHUD.image(named: imgStr) vc.imageView.image = img + vc.titleLabel.textColor = UIColorForPrimaryLabel vc.titleLabel.text = vc.vm.title + vc.bodyLabel.textColor = UIColorForSecondaryLabel vc.bodyLabel.text = vc.vm.message - - vc.tintColor = vc.vm.scene.tintColor - } }() @@ -77,7 +78,6 @@ public extension ProHUD.Configuration { return { (vc) in debugPrint(vc, "layoutSubviews") let config = toastConfig - let scene = vc.vm.scene vc.imageView.snp.makeConstraints { (mk) in @@ -97,16 +97,7 @@ public extension ProHUD.Configuration { mk.leading.trailing.equalTo(vc.titleLabel) mk.bottom.lessThanOrEqualToSuperview().offset(-config.padding) } - if [.default, .loading].contains(vc.vm.scene) { - vc.blurMask(.extraLight) - } else { - vc.blurMask(nil) - } - if let bv = vc.blurView { - vc.backgroundView = bv - } else { - vc.backgroundView.backgroundColor = vc.vm.scene.backgroundColor - } + vc.view.layoutIfNeeded() } }() diff --git a/ProHUD/Toast/ToastController.swift b/ProHUD/Toast/ToastController.swift index c5f76bc..966f2cd 100644 --- a/ProHUD/Toast/ToastController.swift +++ b/ProHUD/Toast/ToastController.swift @@ -24,7 +24,7 @@ public extension ProHUD { /// 标题 internal lazy var titleLabel: UILabel = { let lb = UILabel() - lb.textColor = UIColor.init(white: 0.2, alpha: 1) + lb.textColor = UIColorForPrimaryLabel lb.font = toastConfig.titleFont lb.textAlignment = .justified lb.numberOfLines = toastConfig.titleMaxLines @@ -34,27 +34,25 @@ public extension ProHUD { /// 正文 internal lazy var bodyLabel: UILabel = { let lb = UILabel() - lb.textColor = .darkGray + lb.textColor = UIColorForSecondaryLabel lb.font = toastConfig.bodyFont lb.textAlignment = .justified lb.numberOfLines = toastConfig.bodyMaxLines return lb }() - /// 毛玻璃层 - var blurView: UIVisualEffectView? - - /// 背景层(在iOS13之后window) - var backgroundView = UIView() - - /// 设置颜色 - open var tintColor: UIColor!{ - didSet { - imageView.tintColor = tintColor - titleLabel.textColor = tintColor - bodyLabel.textColor = tintColor + /// 背景层 + var backgroundView: UIVisualEffectView = { + let vev = UIVisualEffectView() + if #available(iOS 13.0, *) { + vev.effect = UIBlurEffect.init(style: .systemMaterial) + } else { + vev.effect = UIBlurEffect.init(style: .extraLight) } - } + vev.layer.masksToBounds = true + vev.layer.cornerRadius = toastConfig.cornerRadius + return vev + }() /// 视图模型 public var vm = ViewModel() @@ -118,23 +116,6 @@ public extension ProHUD { } } - @discardableResult - func blurMask(_ blurEffectStyle: UIBlurEffect.Style?) -> Toast { - if let s = blurEffectStyle { - if let bv = blurView { - bv.effect = UIBlurEffect.init(style: s) - } else { - blurView = UIVisualEffectView(effect: UIBlurEffect.init(style: s)) - blurView?.layer.masksToBounds = true - blurView?.layer.cornerRadius = toastConfig.cornerRadius - } - } else { - blurView?.removeFromSuperview() - blurView = nil - } - return self - } - @discardableResult func update(title: String?) -> Toast { vm.title = title diff --git a/ProHUD/Toast/ToastModel.swift b/ProHUD/Toast/ToastModel.swift index fd4b385..83b4504 100644 --- a/ProHUD/Toast/ToastModel.swift +++ b/ProHUD/Toast/ToastModel.swift @@ -29,27 +29,27 @@ public extension ProHUD.Toast { /// 错误场景 case error - public var backgroundColor: UIColor { - switch self { - case .success: - return UIColor.green - case .warning: - return UIColor.yellow - case .error: - return UIColor.red - default: - return .clear - } - } - - public var tintColor: UIColor { - switch self { - case .success, .error: - return .white - default: - return UIColor.darkGray - } - } +// public var backgroundColor: UIColor { +// switch self { +// case .success: +// return UIColor.green +// case .warning: +// return UIColor.yellow +// case .error: +// return UIColor.red +// default: +// return .clear +// } +// } +// +// public var tintColor: UIColor { +// switch self { +// case .success, .error: +// return .white +// default: +// return UIColor.darkGray +// } +// } } struct ViewModel {