diff --git a/Example/Example/Info.plist b/Example/Example/Info.plist index ff0a7ed..ed7fc0e 100644 --- a/Example/Example/Info.plist +++ b/Example/Example/Info.plist @@ -33,7 +33,7 @@ UIRequiresFullScreen UIStatusBarHidden - + UIStatusBarStyle UIStatusBarStyleDefault UISupportedInterfaceOrientations diff --git a/Example/Example/ViewController.swift b/Example/Example/ViewController.swift index a29bf6e..935c2b1 100644 --- a/Example/Example/ViewController.swift +++ b/Example/Example/ViewController.swift @@ -16,17 +16,12 @@ class ViewController: UIViewController { // Do any additional setup after loading the view. - ProHUD.configAlert { (alert) in - alert.minimizeTimeout = 3 - - } - ProHUD.configGuard { (g) in - g.tintColor = .success - } - ProHUD.configToast { (toast) in -// toast.backgroundColorForScene { (scene) -> UIColor? in -// return UIColor.yellow -// } + ProHUD.config { (cfg) in +// cfg.enableDebugPrint = false + cfg.alert { (a) in + a.forceQuitTimer = 2 + } +// cfg.primaryLabelColor = .purple } } @@ -71,7 +66,8 @@ class ViewController: UIViewController { let g = ProHUD.Guard(title: "请求权限", message: "请打开相机权限开关,否则无法进行测量。") // g.view.tintColor = .warning // g.loadBody(g.description) - + g.loadTitle("呵呵") + g.loadBody("请打开相机权限开关,否则无法进行测量。请打开相机权限开关,否则无法进行测量。") g.loadButton(style: .default, title: "测试弹窗", action: { [weak self] in self?.testToast() }) diff --git a/ProHUD.xcodeproj/project.pbxproj b/ProHUD.xcodeproj/project.pbxproj index 011e03f..11e0a8e 100644 --- a/ProHUD.xcodeproj/project.pbxproj +++ b/ProHUD.xcodeproj/project.pbxproj @@ -12,8 +12,6 @@ CD16490F22EF09D50077988C /* AlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD16490E22EF09D50077988C /* AlertView.swift */; }; CD16491222EF0D900077988C /* HUDView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD16491122EF0D900077988C /* HUDView.swift */; }; CD16491422EF12220077988C /* ProHUD.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CD16491322EF12220077988C /* ProHUD.xcassets */; }; - CD67039022E7F7B60072C96A /* HUDForToast.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD67038F22E7F7B60072C96A /* HUDForToast.swift */; }; - CD67039222E7F7BC0072C96A /* HUDForGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD67039122E7F7BC0072C96A /* HUDForGuard.swift */; }; CD6CD86C22F1858F00F4FD4A /* ToastModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD6CD86B22F1858F00F4FD4A /* ToastModel.swift */; }; CD6CD86E22F185A000F4FD4A /* ToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD6CD86D22F185A000F4FD4A /* ToastView.swift */; }; CD6CD87022F185A700F4FD4A /* ToastController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD6CD86F22F185A700F4FD4A /* ToastController.swift */; }; @@ -35,8 +33,6 @@ CD16490E22EF09D50077988C /* AlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertView.swift; sourceTree = ""; }; CD16491122EF0D900077988C /* HUDView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HUDView.swift; sourceTree = ""; }; CD16491322EF12220077988C /* ProHUD.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = ProHUD.xcassets; sourceTree = ""; }; - CD67038F22E7F7B60072C96A /* HUDForToast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HUDForToast.swift; sourceTree = ""; }; - CD67039122E7F7BC0072C96A /* HUDForGuard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HUDForGuard.swift; sourceTree = ""; }; CD6CD86B22F1858F00F4FD4A /* ToastModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastModel.swift; sourceTree = ""; }; CD6CD86D22F185A000F4FD4A /* ToastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastView.swift; sourceTree = ""; }; CD6CD86F22F185A700F4FD4A /* ToastController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastController.swift; sourceTree = ""; }; @@ -122,8 +118,6 @@ CD95D21F22E72C4C007559A3 /* ProHUD.h */, CD16491322EF12220077988C /* ProHUD.xcassets */, CD95D26A22E72DB3007559A3 /* ProHUD.swift */, - CD67038F22E7F7B60072C96A /* HUDForToast.swift */, - CD67039122E7F7BC0072C96A /* HUDForGuard.swift */, CDB6A07C22EEF19D00AF6CF0 /* HUDConfig.swift */, CDB6A07A22EEF06500AF6CF0 /* HUDController.swift */, CD16491122EF0D900077988C /* HUDView.swift */, @@ -219,12 +213,10 @@ CD6CD87B22F185D600F4FD4A /* GuardView.swift in Sources */, CD95D26922E72DA1007559A3 /* AlertController.swift in Sources */, CD6CD87922F185D000F4FD4A /* GuardConfig.swift in Sources */, - CD67039222E7F7BC0072C96A /* HUDForGuard.swift in Sources */, CDB6A07D22EEF19D00AF6CF0 /* HUDConfig.swift in Sources */, CD16490F22EF09D50077988C /* AlertView.swift in Sources */, CD6CD86E22F185A000F4FD4A /* ToastView.swift in Sources */, CD6CD87222F185AF00F4FD4A /* ToastConfig.swift in Sources */, - CD67039022E7F7B60072C96A /* HUDForToast.swift in Sources */, CD6CD87522F185C200F4FD4A /* GuardController.swift in Sources */, CD6CD87022F185A700F4FD4A /* ToastController.swift in Sources */, CD95D26B22E72DB3007559A3 /* ProHUD.swift in Sources */, diff --git a/ProHUD/Alert/AlertConfig.swift b/ProHUD/Alert/AlertConfig.swift index f95a1cb..ef8be65 100644 --- a/ProHUD/Alert/AlertConfig.swift +++ b/ProHUD/Alert/AlertConfig.swift @@ -1,5 +1,5 @@ // -// AlertConfig.swift +// cfg.alert.swift // ProHUD // // Created by xaoxuu on 2019/7/29. @@ -30,8 +30,6 @@ public extension ProHUD.Configuration { // MARK: 文本样式 /// 标题字体 public var titleFont = UIFont.boldSystemFont(ofSize: 22) - /// 标题颜色 - public var titleColor = UIColorForPrimaryLabel /// 标题最多行数 public var titleMaxLines = Int(1) @@ -40,8 +38,6 @@ public extension ProHUD.Configuration { /// 正文字体 public var bodyFont = UIFont.systemFont(ofSize: 17) - /// 正文颜色 - public var bodyColor = UIColorForSecondaryLabel /// 正文最多行数 public var bodyMaxLines = Int(5) @@ -49,240 +45,257 @@ public extension ProHUD.Configuration { /// 按钮字体 public var buttonFont = UIFont.boldSystemFont(ofSize: 18) - // MARK: 逻辑 - /// 多少秒后显示强制退出的按钮(只有无按钮的弹窗才会出现) - public var minimizeTimeout = TimeInterval(10) - /// 最小化按钮标题 - public var minimizeTitle = String("隐藏窗口") - // MARK: 生命周期 + /// 加载视图 - lazy var loadSubviews: (ProHUD.Alert, Alert) -> Void = { - return { (vc, config) in - debugPrint(vc, "loadSubviews") - if vc.contentView.superview == nil { - vc.view.addSubview(vc.contentView) - vc.contentView.contentView.addSubview(vc.contentStack) - - vc.contentStack.spacing = alertConfig.margin + alertConfig.padding - - vc.contentView.layer.masksToBounds = true - vc.contentView.layer.cornerRadius = alertConfig.cornerRadius - - vc.contentView.snp.makeConstraints { (mk) in - mk.center.equalToSuperview() - mk.width.lessThanOrEqualTo(CGFloat.minimum(UIScreen.main.bounds.width * 0.68, alertConfig.maxWidth)) - } - vc.contentStack.snp.makeConstraints { (mk) in - mk.centerX.equalToSuperview() - mk.top.equalToSuperview().offset(alertConfig.padding) - mk.bottom.equalToSuperview().offset(-alertConfig.padding) - mk.leading.equalToSuperview().offset(alertConfig.padding) - mk.trailing.equalToSuperview().offset(-alertConfig.padding) - } - } - - } - }() + /// - Parameter callback: 回调代码 + public mutating func loadSubviews(_ callback: @escaping (ProHUD.Alert) -> Void) { + privLoadSubviews = callback + } /// 更新视图 - lazy var updateFrame: (ProHUD.Alert, Alert) -> Void = { - return { (vc, config) in - debugPrint(vc, "updateFrame") - let isFirstLayout: Bool - // 图标和文字至少有一个,如果都没有添加到视图中,说明是第一次layout - if vc.textStack.superview == nil && vc.imageView?.superview == nil { - isFirstLayout = true - } else { - isFirstLayout = false - } - let imgStr: String - switch vc.vm.scene { - case .success: - imgStr = "ProHUDSuccess" - case .warning: - imgStr = "ProHUDWarning" - case .error: - imgStr = "ProHUDError" - case .loading: - imgStr = "ProHUDLoading" - case .confirm: - imgStr = "ProHUDMessage" - case .delete: - imgStr = "ProHUDTrash" - default: - imgStr = "ProHUDMessage" - } - let img = vc.vm.icon ?? ProHUD.image(named: imgStr) - if let imgv = vc.imageView { - imgv.image = img - } else { - let icon = UIImageView(image: img) - vc.contentStack.addArrangedSubview(icon) - icon.snp.makeConstraints { (mk) in - mk.top.greaterThanOrEqualTo(vc.contentView).offset(config.padding*2.25) - mk.bottom.lessThanOrEqualTo(vc.contentView).offset(-config.padding*2.25) - mk.leading.greaterThanOrEqualTo(vc.contentView).offset(config.padding*4) - mk.trailing.lessThanOrEqualTo(vc.contentView).offset(-config.padding*4) - } - vc.imageView = icon - } - - // text - if vc.vm.title?.count ?? 0 > 0 || vc.vm.message?.count ?? 0 > 0 { - vc.contentStack.addArrangedSubview(vc.textStack) - vc.textStack.snp.makeConstraints { (mk) in - mk.top.greaterThanOrEqualTo(vc.contentView).offset(config.padding*1.75) - mk.bottom.lessThanOrEqualTo(vc.contentView).offset(-config.padding*1.75) - mk.leading.greaterThanOrEqualTo(vc.contentView).offset(config.padding*2) - mk.trailing.lessThanOrEqualTo(vc.contentView).offset(-config.padding*2) - } - if vc.vm.title?.count ?? 0 > 0 { - if let lb = vc.titleLabel { - lb.text = vc.vm.title - } else { - let title = UILabel() - title.textAlignment = .center - title.numberOfLines = config.titleMaxLines - title.textColor = config.titleColor - title.text = vc.vm.title - vc.textStack.addArrangedSubview(title) - vc.titleLabel = title - } - if vc.vm.message?.count ?? 0 > 0 { - // 有message - vc.titleLabel?.font = config.titleFont - } else { - // 没有message - vc.titleLabel?.font = config.boldTextFont - } - } else { - vc.titleLabel?.removeFromSuperview() - } - if vc.vm.message?.count ?? 0 > 0 { - if let lb = vc.messageLabel { - lb.text = vc.vm.message - } else { - let body = UILabel() - body.textAlignment = .center - body.font = config.bodyFont - body.numberOfLines = config.bodyMaxLines - body.textColor = config.bodyColor - body.text = vc.vm.message - vc.textStack.addArrangedSubview(body) - vc.messageLabel = body - } - if vc.vm.title?.count ?? 0 > 0 { - // 有title - vc.messageLabel?.font = config.bodyFont - } else { - // 没有title - vc.messageLabel?.font = config.boldTextFont - } - } else { - vc.messageLabel?.removeFromSuperview() - } - } else { - vc.textStack.removeFromSuperview() - } - if vc.actionStack.superview != nil { - if isFirstLayout { - vc.contentStack.addArrangedSubview(vc.actionStack) - } else { - vc.actionStack.transform = .init(scaleX: 1, y: 0.001) - UIView.animateForAlert { - vc.contentStack.addArrangedSubview(vc.actionStack) - vc.view.layoutIfNeeded() - } - } - // 适配横竖屏和iPad - if isPortrait == false { - vc.actionStack.axis = .horizontal - vc.actionStack.alignment = .fill - vc.actionStack.distribution = .fillEqually - } - vc.actionStack.snp.makeConstraints { (mk) in - mk.width.greaterThanOrEqualTo(200) - mk.leading.trailing.equalToSuperview() - } - if isFirstLayout == false { - UIView.animateForAlert { - vc.actionStack.transform = .identity - } - } - - } - - if isFirstLayout { - vc.view.layoutIfNeeded() - vc.imageView?.transform = .init(scaleX: 0.75, y: 0.75) - UIView.animateForAlert { - vc.imageView?.transform = .identity - vc.view.layoutIfNeeded() - } - } else { - UIView.animateForAlert { - vc.view.layoutIfNeeded() - } - } - } - }() + /// - Parameter callback: 回调代码 + public mutating func reloadData(_ callback: @escaping (ProHUD.Alert) -> Void) { + privReloadData = callback + } - /// 加载强制按钮 - lazy var showNavButtons: (ProHUD.Alert, Alert) -> Void = { - return { (vc, config) in - debugPrint(vc, "showNavButtons") - let btn = ProHUD.Alert.Button.minimizeButton() - let bg = ProHUD.BlurView() - bg.layer.masksToBounds = true - bg.layer.cornerRadius = config.cornerRadius - if let last = vc.view.subviews.last { - vc.view.insertSubview(bg, belowSubview: last) + /// 多少秒后显示强制退出的按钮(只有无按钮的弹窗才会出现) + public var forceQuitTimer = TimeInterval(10) + + /// 强制退出按钮标题 + public var forceQuitTitle = "隐藏窗口" + + /// 加载强制退出按钮 + /// - Parameter callback: 回调代码 + public mutating func loadForceQuitButton(_ callback: @escaping (ProHUD.Alert) -> Void) { + privLoadForceQuitButton = callback + } + + } +} + + +// MARK: - 默认实现 + +internal extension ProHUD.Configuration.Alert { + var loadSubviews: (ProHUD.Alert) -> Void { + return privLoadSubviews + } + + var reloadData: (ProHUD.Alert) -> Void { + return privReloadData + } + + var loadForceQuitButton: (ProHUD.Alert) -> Void { + return privLoadForceQuitButton + } +} + +fileprivate var privLoadSubviews: (ProHUD.Alert) -> Void = { + return { (vc) in + debug(vc, "loadSubviews") + let config = cfg.alert + if vc.contentView.superview == nil { + vc.view.addSubview(vc.contentView) + vc.contentView.contentView.addSubview(vc.contentStack) + + vc.contentStack.spacing = cfg.alert.margin + cfg.alert.padding + + vc.contentView.layer.masksToBounds = true + vc.contentView.layer.cornerRadius = cfg.alert.cornerRadius + + vc.contentView.snp.makeConstraints { (mk) in + mk.center.equalToSuperview() + mk.width.lessThanOrEqualTo(CGFloat.minimum(UIScreen.main.bounds.width * 0.68, cfg.alert.maxWidth)) + } + vc.contentStack.snp.makeConstraints { (mk) in + mk.centerX.equalToSuperview() + mk.top.equalToSuperview().offset(cfg.alert.padding) + mk.bottom.equalToSuperview().offset(-cfg.alert.padding) + mk.leading.equalToSuperview().offset(cfg.alert.padding) + mk.trailing.equalToSuperview().offset(-cfg.alert.padding) + } + } + + } +}() + +fileprivate var privReloadData: (ProHUD.Alert) -> Void = { + return { (vc) in + debug(vc, "reloadData") + let config = cfg.alert + let isFirstLayout: Bool + // 图标和文字至少有一个,如果都没有添加到视图中,说明是第一次layout + if vc.textStack.superview == nil && vc.imageView?.superview == nil { + isFirstLayout = true + } else { + isFirstLayout = false + } + let imgStr: String + switch vc.vm.scene { + case .success: + imgStr = "ProHUDSuccess" + case .warning: + imgStr = "ProHUDWarning" + case .error: + imgStr = "ProHUDError" + case .loading: + imgStr = "ProHUDLoading" + case .confirm: + imgStr = "ProHUDMessage" + case .delete: + imgStr = "ProHUDTrash" + default: + imgStr = "ProHUDMessage" + } + let img = vc.vm.icon ?? ProHUD.image(named: imgStr) + if let imgv = vc.imageView { + imgv.image = img + } else { + let icon = UIImageView(image: img) + vc.contentStack.addArrangedSubview(icon) + icon.snp.makeConstraints { (mk) in + mk.top.greaterThanOrEqualTo(vc.contentView).offset(config.padding*2.25) + mk.bottom.lessThanOrEqualTo(vc.contentView).offset(-config.padding*2.25) + mk.leading.greaterThanOrEqualTo(vc.contentView).offset(config.padding*4) + mk.trailing.lessThanOrEqualTo(vc.contentView).offset(-config.padding*4) + } + vc.imageView = icon + } + + // text + if vc.vm.title?.count ?? 0 > 0 || vc.vm.message?.count ?? 0 > 0 { + vc.contentStack.addArrangedSubview(vc.textStack) + vc.textStack.snp.makeConstraints { (mk) in + mk.top.greaterThanOrEqualTo(vc.contentView).offset(config.padding*1.75) + mk.bottom.lessThanOrEqualTo(vc.contentView).offset(-config.padding*1.75) + mk.leading.greaterThanOrEqualTo(vc.contentView).offset(config.padding*2) + mk.trailing.lessThanOrEqualTo(vc.contentView).offset(-config.padding*2) + } + if vc.vm.title?.count ?? 0 > 0 { + if let lb = vc.titleLabel { + lb.text = vc.vm.title } else { - vc.view.addSubview(bg) + let title = UILabel() + title.textAlignment = .center + title.numberOfLines = config.titleMaxLines + title.textColor = cfg.primaryLabelColor + title.text = vc.vm.title + vc.textStack.addArrangedSubview(title) + vc.titleLabel = title } - bg.snp.makeConstraints { (mk) in - mk.leading.trailing.equalTo(vc.contentView) - mk.top.equalTo(vc.contentView.snp.bottom).offset(config.margin) + if vc.vm.message?.count ?? 0 > 0 { + // 有message + vc.titleLabel?.font = config.titleFont + } else { + // 没有message + vc.titleLabel?.font = config.boldTextFont } - bg.contentView.addSubview(btn) - btn.snp.makeConstraints { (mk) in - mk.edges.equalToSuperview() + } else { + vc.titleLabel?.removeFromSuperview() + } + if vc.vm.message?.count ?? 0 > 0 { + if let lb = vc.messageLabel { + lb.text = vc.vm.message + } else { + let body = UILabel() + body.textAlignment = .center + body.font = config.bodyFont + body.numberOfLines = config.bodyMaxLines + body.textColor = cfg.secondaryLabelColor + body.text = vc.vm.message + vc.textStack.addArrangedSubview(body) + vc.messageLabel = body } - bg.alpha = 0 - bg.layoutIfNeeded() - bg.transform = .init(translationX: 0, y: -2*(config.margin+bg.frame.size.height)) + if vc.vm.title?.count ?? 0 > 0 { + // 有title + vc.messageLabel?.font = config.bodyFont + } else { + // 没有title + vc.messageLabel?.font = config.boldTextFont + } + } else { + vc.messageLabel?.removeFromSuperview() + } + } else { + vc.textStack.removeFromSuperview() + } + if vc.actionStack.superview != nil { + if isFirstLayout { + vc.contentStack.addArrangedSubview(vc.actionStack) + } else { + vc.actionStack.transform = .init(scaleX: 1, y: 0.001) UIView.animateForAlert { - bg.alpha = 1 - bg.transform = .identity - } - vc.addTouchUpAction(for: btn) { [weak vc] in - debugPrint("点击了隐藏") - vc?.minimizeCallback?() - vc?.remove() + vc.contentStack.addArrangedSubview(vc.actionStack) + vc.view.layoutIfNeeded() } } - }() - - /// 加载视图 - /// - Parameter callback: 回调代码 - public mutating func loadSubviews(_ callback: @escaping (ProHUD.Alert, Alert) -> Void) { - loadSubviews = callback + // 适配横竖屏和iPad + if isPortrait == false { + vc.actionStack.axis = .horizontal + vc.actionStack.alignment = .fill + vc.actionStack.distribution = .fillEqually + } + vc.actionStack.snp.makeConstraints { (mk) in + mk.width.greaterThanOrEqualTo(200) + mk.leading.trailing.equalToSuperview() + } + if isFirstLayout == false { + UIView.animateForAlert { + vc.actionStack.transform = .identity + } + } + } - /// 更新视图 - /// - Parameter callback: 回调代码 - public mutating func updateFrame(_ callback: @escaping (ProHUD.Alert, Alert) -> Void) { - updateFrame = callback + if isFirstLayout { + vc.view.layoutIfNeeded() + vc.imageView?.transform = .init(scaleX: 0.75, y: 0.75) + UIView.animateForAlert { + vc.imageView?.transform = .identity + vc.view.layoutIfNeeded() + } + } else { + UIView.animateForAlert { + vc.view.layoutIfNeeded() + } } - } -} +}() -internal var alertConfig = ProHUD.Configuration.Alert() - -public extension ProHUD { - static func configAlert(_ config: (inout Configuration.Alert) -> Void) { - config(&alertConfig) +fileprivate var privLoadForceQuitButton: (ProHUD.Alert) -> Void = { + return { (vc) in + debug(vc, "showNavButtons") + let config = cfg.alert + let btn = ProHUD.Alert.Button.forceQuitButton() + btn.setTitle(cfg.alert.forceQuitTitle, for: .normal) + let bg = ProHUD.BlurView() + bg.layer.masksToBounds = true + bg.layer.cornerRadius = config.cornerRadius + if let last = vc.view.subviews.last { + vc.view.insertSubview(bg, belowSubview: last) + } else { + vc.view.addSubview(bg) + } + bg.snp.makeConstraints { (mk) in + mk.leading.trailing.equalTo(vc.contentView) + mk.top.equalTo(vc.contentView.snp.bottom).offset(config.margin) + } + bg.contentView.addSubview(btn) + btn.snp.makeConstraints { (mk) in + mk.edges.equalToSuperview() + } + bg.alpha = 0 + bg.layoutIfNeeded() + bg.transform = .init(translationX: 0, y: -2*(config.margin+bg.frame.size.height)) + UIView.animateForAlert { + bg.alpha = 1 + bg.transform = .identity + } + vc.addTouchUpAction(for: btn) { [weak vc] in + debug("点击了隐藏") + vc?.minimizeCallback?() + vc?.remove() + } } -} +}() diff --git a/ProHUD/Alert/AlertController.swift b/ProHUD/Alert/AlertController.swift index 3f130d1..2a42ac5 100644 --- a/ProHUD/Alert/AlertController.swift +++ b/ProHUD/Alert/AlertController.swift @@ -18,14 +18,14 @@ public extension ProHUD { /// 正文(包括icon、textStack、actionStack) internal var contentStack: StackContainer = { let stack = StackContainer() - stack.spacing = alertConfig.margin + stack.spacing = cfg.alert.margin return stack }() /// 文本区域 internal var textStack: StackContainer = { let stack = StackContainer() - stack.spacing = alertConfig.margin + stack.spacing = cfg.alert.margin return stack }() internal var imageView: UIImageView? @@ -35,7 +35,7 @@ public extension ProHUD { internal var actionStack: StackContainer = { let stack = StackContainer() stack.alignment = .fill - stack.spacing = alertConfig.margin + stack.spacing = cfg.alert.margin return stack }() @@ -56,7 +56,7 @@ public extension ProHUD { /// - Parameter icon: 图标 public convenience init(scene: Scene = .default, title: String? = nil, message: String? = nil, icon: UIImage? = nil) { self.init() - view.tintColor = alertConfig.tintColor + view.tintColor = cfg.alert.tintColor vm.scene = scene vm.title = title vm.message = message @@ -151,7 +151,7 @@ public extension ProHUD { vm.message = message vm.scene = scene vm.icon = icon - alertConfig.updateFrame(self, alertConfig) + cfg.alert.reloadData(self) return self } @@ -217,8 +217,8 @@ fileprivate extension ProHUD.Alert { willLayout = DispatchWorkItem(block: { [weak self] in if let a = self { // 布局 - alertConfig.loadSubviews(a, alertConfig) - alertConfig.updateFrame(a, alertConfig) + cfg.alert.loadSubviews(a) + cfg.alert.reloadData(a) // 超时 if let t = a.timeout, t > 0 { a.timeoutBlock = DispatchWorkItem(block: { [weak self] in @@ -229,13 +229,13 @@ fileprivate extension ProHUD.Alert { a.timeoutBlock = nil } // 顶部按钮 - if alertConfig.minimizeTimeout > 0 && self?.actionStack.superview == nil { + if cfg.alert.forceQuitTimer > 0 && self?.actionStack.superview == nil { a.showNavButtonsBlock = DispatchWorkItem(block: { [weak self] in if let s = self { - alertConfig.showNavButtons(s, alertConfig) + cfg.alert.loadForceQuitButton(s) } }) - DispatchQueue.main.asyncAfter(deadline: .now()+alertConfig.minimizeTimeout, execute: a.showNavButtonsBlock!) + DispatchQueue.main.asyncAfter(deadline: .now()+cfg.alert.forceQuitTimer, execute: a.showNavButtonsBlock!) } } }) @@ -394,7 +394,7 @@ fileprivate extension ProHUD { } else if alerts.count == 1 { alerts.removeAll() } else { - debugPrint("漏洞:已经没有alert了") + debug("漏洞:已经没有alert了") } } diff --git a/ProHUD/Alert/AlertView.swift b/ProHUD/Alert/AlertView.swift index 8521f4b..683e82b 100644 --- a/ProHUD/Alert/AlertView.swift +++ b/ProHUD/Alert/AlertView.swift @@ -13,15 +13,15 @@ internal extension ProHUD.Alert { 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 + btn.layer.cornerRadius = cfg.alert.cornerRadius / 2 + btn.titleLabel?.font = cfg.alert.buttonFont return btn } func update(style: UIAlertAction.Style) { let pd = CGFloat(8) if style != .cancel { - backgroundColor = dynamicColor.withAlphaComponent(0.04) + backgroundColor = cfg.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) @@ -32,21 +32,20 @@ internal extension ProHUD.Alert { case .destructive: setTitleColor(.init(red: 244/255, green: 67/255, blue: 54/255, alpha: 1), for: .normal) case .cancel: - setTitleColor(UIColorForSecondaryLabel, for: .normal) + setTitleColor(cfg.secondaryLabelColor, for: .normal) @unknown default: break } tag = style.rawValue } - class func minimizeButton() -> UIButton { + class func forceQuitButton() -> UIButton { let btn = Button(type: .system) - let pd = alertConfig.padding/2 + let pd = cfg.alert.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 + btn.titleLabel?.font = cfg.alert.buttonFont return btn } diff --git a/ProHUD/Guard/GuardConfig.swift b/ProHUD/Guard/GuardConfig.swift index 72e5b19..bfbe1d3 100644 --- a/ProHUD/Guard/GuardConfig.swift +++ b/ProHUD/Guard/GuardConfig.swift @@ -1,5 +1,5 @@ // -// GuardConfig.swift +// cfg.guard.swift // ProHUD // // Created by xaoxuu on 2019/7/31. @@ -29,13 +29,9 @@ public extension ProHUD.Configuration { // MARK: 文本样式 /// 标题字体 public var titleFont = UIFont.boldSystemFont(ofSize: 22) - /// 标题颜色 - public var titleColor = UIColorForPrimaryLabel /// 正文字体 public var bodyFont = UIFont.systemFont(ofSize: 18) - /// 正文颜色 - public var bodyColor = UIColorForSecondaryLabel // MARK: 按钮样式 /// 按钮字体 @@ -45,111 +41,89 @@ public extension ProHUD.Configuration { /// 按钮圆角半径 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.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 + /// - Parameter callback: 回调代码 + public mutating func loadSubviews(_ callback: @escaping (ProHUD.Guard) -> Void) { + privLoadSubviews = callback + } + + /// 更新视图 + /// - Parameter callback: 回调代码 + public mutating func reloadData(_ callback: @escaping (ProHUD.Guard) -> Void) { + privReloadData = callback + } + + } +} + +// MARK: - 默认实现 + +internal extension ProHUD.Configuration.Guard { + var loadSubviews: (ProHUD.Guard) -> Void { + return privLoadSubviews + } + var reloadData: (ProHUD.Guard) -> Void { + return privReloadData + } +} + +fileprivate var privLoadSubviews: (ProHUD.Guard) -> Void = { + return { (vc) in + debug(vc, "loadSubviews") + let config = cfg.guard + // background + vc.view.tintColor = config.tintColor + vc.view.backgroundColor = UIColor(white: 0, alpha: 0) + vc.view.addSubview(vc.contentView) + vc.contentView.contentView.addSubview(vc.contentStack) + vc.contentStack.addArrangedSubview(vc.textStack) + vc.contentStack.addArrangedSubview(vc.actionStack) + } +}() + +fileprivate var privReloadData: (ProHUD.Guard) -> Void = { + return { (vc) in + debug(vc, "reloadData") + let config = cfg.guard + // 更新布局 + 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 { - vc.contentView.layer.shadowRadius = 4 - vc.contentView.layer.shadowOffset = .init(width: 0, height: 2) - vc.contentView.layer.shadowOpacity = 0.12 + mk.bottom.equalToSuperview() } - 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) - + } else if UIDevice.current.userInterfaceIdiom == .pad { + mk.centerY.equalToSuperview() } - }() - - /// 更新视图 - lazy var updateFrame: (ProHUD.Guard, Guard) -> Void = { - return { (vc, config) in - debugPrint(vc, "updateFrame") + mk.width.equalTo(width) + } + // stack + 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) } - }() - - /// 加载视图 - /// - Parameter callback: 回调代码 - public mutating func loadSubviews(_ callback: @escaping (ProHUD.Guard, Guard) -> Void) { - loadSubviews = callback } - - /// 更新视图 - /// - Parameter callback: 回调代码 - 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 7e3092e..aa1ab21 100644 --- a/ProHUD/Guard/GuardController.swift +++ b/ProHUD/Guard/GuardController.swift @@ -17,7 +17,7 @@ public extension ProHUD { /// 内容容器(包括textStack、actionStack) public var contentStack: StackContainer = { let stack = StackContainer() - stack.spacing = guardConfig.padding + guardConfig.margin + stack.spacing = cfg.guard.padding + cfg.guard.margin stack.alignment = .fill return stack }() @@ -25,19 +25,19 @@ public extension ProHUD { /// 文本区域 public var textStack: StackContainer = { let stack = StackContainer() - stack.spacing = guardConfig.margin + stack.spacing = cfg.guard.margin stack.alignment = .fill return stack }() - public var titleLabel: UILabel? - public var bodyLabel: UILabel? +// public var titleLabel: UILabel? +// public var bodyLabel: UILabel? /// 操作区域 public var actionStack: StackContainer = { let stack = StackContainer() stack.alignment = .fill - stack.spacing = guardConfig.margin + stack.spacing = cfg.guard.margin return stack }() @@ -57,15 +57,15 @@ public extension ProHUD { public convenience init(title: String? = nil, message: String? = nil) { self.init() view = View() - view.tintColor = guardConfig.tintColor + view.tintColor = cfg.guard.tintColor if let _ = title { loadTitle(title) } if let _ = message { loadBody(message) } - guardConfig.loadSubviews(self, guardConfig) -// willLayoutSubviews() + cfg.guard.loadSubviews(self) + cfg.guard.reloadData(self) // 点击 let tap = UITapGestureRecognizer(target: self, action: #selector(privDidTapped(_:))) @@ -81,7 +81,7 @@ public extension ProHUD { } deinit { - debugPrint(self, "deinit") + debug(self, "deinit") } public func push(to viewController: UIViewController? = nil) { @@ -106,7 +106,7 @@ public extension ProHUD { public func pop() { if displaying { - debugPrint("pop") + debug("pop") displaying = false view.isUserInteractionEnabled = false self.removeFromParent() @@ -126,21 +126,31 @@ public extension ProHUD.Guard { @discardableResult func loadTitle(_ text: String?) -> UILabel { - guardConfig.loadTitleLabel(self, guardConfig) - let lb = titleLabel! + let lb = UILabel() + lb.font = cfg.guard.titleFont + lb.textColor = cfg.primaryLabelColor + lb.numberOfLines = 0 + lb.textAlignment = .justified lb.text = text - if textStack.arrangedSubviews.count > 0 { - textStack.insertArrangedSubview(lb, at: 0) + textStack.addArrangedSubview(lb) + if #available(iOS 11.0, *) { + let count = textStack.arrangedSubviews.count + if count > 1 { + textStack.setCustomSpacing(cfg.guard.margin * 2, after: textStack.arrangedSubviews[count-2]) + } } else { - textStack.addArrangedSubview(lb) + // Fallback on earlier versions } return lb } @discardableResult func loadBody(_ text: String?) -> UILabel { - guardConfig.loadBodyLabel(self, guardConfig) - let lb = bodyLabel! + let lb = UILabel() + lb.font = cfg.guard.bodyFont + lb.textColor = cfg.secondaryLabelColor + lb.numberOfLines = 0 + lb.textAlignment = .justified lb.text = text textStack.addArrangedSubview(lb) return lb @@ -149,7 +159,7 @@ public extension ProHUD.Guard { @discardableResult func loadButton(style: UIAlertAction.Style, title: String?, action: (() -> Void)? = nil) -> UIButton { let btn = Button.actionButton(title: title) - btn.titleLabel?.font = guardConfig.buttonFont + btn.titleLabel?.font = cfg.guard.buttonFont if actionStack.superview == nil { contentStack.addArrangedSubview(actionStack) } @@ -189,7 +199,7 @@ fileprivate extension ProHUD.Guard { func translateOut() { view.backgroundColor = UIColor(white: 0, alpha: 0) - contentView.transform = .init(translationX: 0, y: view.frame.size.height - contentView.frame.minY + guardConfig.margin) + contentView.transform = .init(translationX: 0, y: view.frame.size.height - contentView.frame.minY + cfg.guard.margin) } diff --git a/ProHUD/Guard/GuardView.swift b/ProHUD/Guard/GuardView.swift index c01a46b..0a1566f 100644 --- a/ProHUD/Guard/GuardView.swift +++ b/ProHUD/Guard/GuardView.swift @@ -42,8 +42,8 @@ internal extension ProHUD.Guard { 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 + btn.layer.cornerRadius = cfg.guard.buttonCornerRadius + btn.titleLabel?.font = cfg.guard.buttonFont return btn } @@ -62,7 +62,7 @@ internal extension ProHUD.Guard { backgroundColor = .init(red: 244/255, green: 67/255, blue: 54/255, alpha: 1) setTitleColor(.white, for: .normal) case .cancel: - setTitleColor(UIColorForSecondaryLabel, for: .normal) + setTitleColor(cfg.secondaryLabelColor, for: .normal) @unknown default: break } diff --git a/ProHUD/HUDConfig.swift b/ProHUD/HUDConfig.swift index fa1a850..b1e7c1c 100644 --- a/ProHUD/HUDConfig.swift +++ b/ProHUD/HUDConfig.swift @@ -11,9 +11,40 @@ import UIKit public extension ProHUD { struct Configuration { - internal var toast = Toast() - internal var alert = Alert() - internal var `guard` = Guard() + /// 是否允许Debug模式输出 + public var enableDebugPrint = true + + /// 动态颜色(适配iOS13) + public lazy 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) + }() + + /// 主标签文本颜色 + public lazy var primaryLabelColor: UIColor = { + return dynamicColor.withAlphaComponent(0.75) + }() + + /// 次级标签文本颜色 + public lazy var secondaryLabelColor: UIColor = { + return dynamicColor.withAlphaComponent(0.6) + }() + + + public var toast = Toast() + public var alert = Alert() + public var `guard` = Guard() /// Toast的配置 /// - Parameter callback: 回调 @@ -36,3 +67,10 @@ public extension ProHUD { } } +internal var cfg = ProHUD.Configuration() + +public extension ProHUD { + static func config(_ config: (inout Configuration) -> Void) { + config(&cfg) + } +} diff --git a/ProHUD/HUDController.swift b/ProHUD/HUDController.swift index 925065b..1ad3c99 100644 --- a/ProHUD/HUDController.swift +++ b/ProHUD/HUDController.swift @@ -25,7 +25,7 @@ public class HUDController: UIViewController { init() { super.init(nibName: nil, bundle: nil) - print(self, "init") + debug(self, "init") } required public init?(coder: NSCoder) { @@ -33,7 +33,7 @@ public class HUDController: UIViewController { } deinit { - debugPrint(self, "deinit") + debug(self, "deinit") } @@ -48,14 +48,6 @@ public class HUDController: UIViewController { internal extension HUDController { -// func animateOut(completion: ((Bool) -> Void)? = nil) { -// UIView.animateForAlertBuildOut(animations: { -// self.view.alpha = 0 -// }) { (done) in -// completion?(done) -// } -// } - func addTouchUpAction(for button: UIButton, action: @escaping () -> Void) { button.addTarget(self, action: #selector(didTappedButton(_:)), for: .touchUpInside) buttonEvents[button] = action diff --git a/ProHUD/HUDForGuard.swift b/ProHUD/HUDForGuard.swift deleted file mode 100644 index 8e2c53a..0000000 --- a/ProHUD/HUDForGuard.swift +++ /dev/null @@ -1,73 +0,0 @@ -// -// Guard.swift -// ProHUD -// -// Created by xaoxuu on 2019/7/24. -// Copyright © 2019 Titan Studio. All rights reserved. -// - -import UIKit - -//public extension ProHUD { -// class Guard: Element { -// -// public class View: UIView { -// public var stack = UIStackView() -// -// public class Button: UIButton { -// -// } -// } -// -// -// public convenience init(title: String? = nil, message: String? = nil) { -// self.init() -// vm.title = title -// vm.message = message -// } -// -// public override func viewDidDisappear(_ animated: Bool) { -// vm.disappearCallback?() -// } -// -// } -// -// -// @discardableResult -// func show(_ guard: Guard) -> Guard { -// return `guard` -// } -// -// @discardableResult -// func showGuard(title: String? = nil, message: String? = nil) -> Guard { -// return ProHUD.shared.show(Guard(title: title, message: message)) -// } -// -// @discardableResult -// class func showGuard(title: String? = nil, message: String? = nil) -> Guard { -// return shared.showGuard(title: title, message: message) -// } -// -//} -// -//public extension ProHUD.Guard { -// -// @discardableResult -// func addAction(style: UIAlertAction.Style, title: String?, didTapped: ((View.Button) -> Void)?) -> ProHUD.Guard { -// -// return self -// } -// -// @discardableResult -// func addAction(custom: (View.Button) -> Void, didTapped: ((View.Button) -> Void)?) -> ProHUD.Guard { -// -// return self -// } -// -// @discardableResult -// func didDisappear(_ callback: (() -> Void)?) -> ProHUD.Guard { -// vm.disappearCallback = callback -// return self -// } -// -//} diff --git a/ProHUD/HUDForToast.swift b/ProHUD/HUDForToast.swift deleted file mode 100644 index f02edc9..0000000 --- a/ProHUD/HUDForToast.swift +++ /dev/null @@ -1,61 +0,0 @@ -// -// Toast.swift -// ProHUD -// -// Created by xaoxuu on 2019/7/24. -// Copyright © 2019 Titan Studio. All rights reserved. -// - -import UIKit - - -//public extension ProHUD { -// class Toast: HUDController { -// -// public class View: UIView { -// public var stack = UIStackView() -// -// public class Button: UIButton { -// -// } -// } -// -// public convenience init(scene: HUDScene = .default, title: String?, message: String?, icon: UIImage?) { -// self.init() -// vm.scene = scene -// vm.title = title -// vm.message = message -// vm.icon = icon -// switch scene { -// case .loading: -// vm.timeout = nil -// default: -// vm.timeout = 2 -// } -// } -// -// /// 设置超时时间 -// /// - Parameter timeout: 超时时间 -// public func timeout(_ timeout: TimeInterval?) -> Toast { -// vm.timeout = timeout -// return self -// } -// -// } -// -// @discardableResult -// func show(_ toast: Toast) -> Toast { -// return toast -// } -// -// @discardableResult -// func showToast(scene: HUDScene = .default, title: String?, message: String?, icon: UIImage? = nil) -> Toast { -// return ProHUD.shared.show(Toast(scene: scene, title: title, message: message, icon: icon)) -// } -// -// @discardableResult -// class func showAlert(scene: HUDScene = .default, title: String?, message: String?, icon: UIImage? = nil) -> Toast { -// return shared.showToast(scene: scene, title: title, message: message, icon: icon) -// } -// -//} diff --git a/ProHUD/HUDView.swift b/ProHUD/HUDView.swift index dbdb20c..746c0a2 100644 --- a/ProHUD/HUDView.swift +++ b/ProHUD/HUDView.swift @@ -38,7 +38,7 @@ public extension ProHUD { public override init(frame: CGRect) { super.init(frame: frame) - spacing = alertConfig.margin + spacing = cfg.alert.margin distribution = .fill alignment = .center axis = .vertical @@ -58,10 +58,8 @@ public extension ProHUD { 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) } } diff --git a/ProHUD/ProHUD.swift b/ProHUD/ProHUD.swift index ccc657f..bb18170 100644 --- a/ProHUD/ProHUD.swift +++ b/ProHUD/ProHUD.swift @@ -14,6 +14,10 @@ public class ProHUD { public static let shared = ProHUD() + public var config: Configuration { + return cfg + } + internal var toasts = [Toast]() internal var alerts = [Alert]() @@ -22,9 +26,11 @@ public class ProHUD { } +// MARK: - Utilities internal extension ProHUD { + /// 获取Bundle static var bundle: Bundle { var b = Bundle.init(for: ProHUD.Alert.self) let p = b.path(forResource: "ProHUD", ofType: "bundle") @@ -33,7 +39,7 @@ internal extension ProHUD { } return b } - + /// 获取Image static func image(named: String) -> UIImage? { return UIImage.init(named: named, in: bundle, compatibleWith: nil) } @@ -41,63 +47,26 @@ internal extension ProHUD { } + +/// 是否是手机竖屏模式 internal var isPortrait: Bool { - if UIScreen.main.bounds.width < 500 { - return true - } else { - 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 + if UIDevice.current.userInterfaceIdiom == .phone { + if UIApplication.shared.statusBarOrientation.isPortrait { + debug("当前是手机竖屏模式") + return true } else { - // Fallback on earlier versions + debug("当前是手机横屏模式") } - return .init(white: 0.2, alpha: 1) + } else { + debug("非手机设备(unspecified、iPad、tv、carPlay)") } - - var dynamicPrimaryLabelColor: UIColor { - return dynamicColor.withAlphaComponent(0.75) - } - var dynamicSecondaryLabelColor: UIColor { - return dynamicColor.withAlphaComponent(0.6) - } - + return false } + +/// 可控Debug输出 +internal func debug(_ items: Any..., separator: String = " ", terminator: String = "\n") { + if cfg.enableDebugPrint { + debugPrint(items, separator: separator, terminator: terminator) + } +} + diff --git a/ProHUD/Toast/ToastConfig.swift b/ProHUD/Toast/ToastConfig.swift index 41f62c9..32e2078 100644 --- a/ProHUD/Toast/ToastConfig.swift +++ b/ProHUD/Toast/ToastConfig.swift @@ -1,5 +1,5 @@ // -// ToastConfig.swift +// cfg.toast.swift // ProHUD // // Created by xaoxuu on 2019/7/31. @@ -10,116 +10,118 @@ import SnapKit public extension ProHUD.Configuration { struct Toast { + // MARK: 卡片样式 /// 最大宽度(用于优化横屏或者iPad显示) public var maxWidth = CGFloat(556) - /// 标题字体 - public var titleFont = UIFont.boldSystemFont(ofSize: 18) - /// 正文字体 - public var bodyFont = UIFont.systemFont(ofSize: 16) - /// 标题最多行数 - public var titleMaxLines = Int(1) - /// 正文最多行数 - public var bodyMaxLines = Int(10) /// 圆角半径 public var cornerRadius = CGFloat(12) - + /// 余量:元素与元素之间的距离 public var margin = CGFloat(8) - + /// 填充:元素内部控件距离元素边界的距离 public var padding = CGFloat(16) + // MARK: 图标样式 + /// 图标、default按钮的颜色 + public var tintColor: UIColor? + /// 图标尺寸 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) - - } - }() + // MARK: 文本样式 + /// 标题字体 + public var titleFont = UIFont.boldSystemFont(ofSize: 18) + /// 标题最多行数 + public var titleMaxLines = Int(1) - /// 更新视图 - lazy var reloadData: (ProHUD.Toast) -> Void = { - return { (vc) in - debugPrint(vc, "reloadData") - // 设置数据 - let imgStr: String - switch vc.vm.scene { - case .success: - imgStr = "ProHUDSuccess" - case .warning: - imgStr = "ProHUDWarning" - case .error: - imgStr = "ProHUDError" - case .loading: - imgStr = "ProHUDLoading" - case .confirm: - imgStr = "ProHUDMessage" - case .delete: - imgStr = "ProHUDTrash" - default: - imgStr = "ProHUDMessage" - } - 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 - } - }() + /// 正文字体 + public var bodyFont = UIFont.systemFont(ofSize: 16) + /// 正文最多行数 + public var bodyMaxLines = Int(10) - /// 更新视图 - lazy var layoutSubviews: (ProHUD.Toast) -> Void = { - return { (vc) in - debugPrint(vc, "layoutSubviews") - let config = toastConfig - let scene = vc.vm.scene - - vc.imageView.snp.makeConstraints { (mk) in - mk.top.equalToSuperview().offset(config.padding) - mk.leading.equalToSuperview().offset(config.padding) - mk.bottom.lessThanOrEqualToSuperview().offset(-config.padding) - mk.width.height.equalTo(config.iconSize) - } - vc.titleLabel.snp.makeConstraints { (mk) in - mk.top.equalToSuperview().offset(config.padding) - mk.leading.equalTo(vc.imageView.snp.trailing).offset(config.margin) - mk.leading.greaterThanOrEqualToSuperview().offset(config.padding) - mk.trailing.equalToSuperview().offset(-config.padding) - } - vc.bodyLabel.snp.makeConstraints { (mk) in - mk.top.equalTo(vc.titleLabel.snp.bottom).offset(config.margin) - mk.leading.trailing.equalTo(vc.titleLabel) - mk.bottom.lessThanOrEqualToSuperview().offset(-config.padding) - } - - vc.view.layoutIfNeeded() - } - }() - /// 加载视图 + /// 加载视图(如果需要完全自定义整个View,可以重写这个) /// - Parameter callback: 回调代码 public mutating func loadSubviews(_ callback: @escaping (ProHUD.Toast) -> Void) { - loadSubviews = callback + privLoadSubviews = callback } /// 更新视图 /// - Parameter callback: 回调代码 public mutating func reloadData(_ callback: @escaping (ProHUD.Toast) -> Void) { - reloadData = callback + privReloadData = callback } } } -internal var toastConfig = ProHUD.Configuration.Toast() +// MARK: - 默认实现 -public extension ProHUD { - static func configToast(_ config: (inout Configuration.Toast) -> Void) { - config(&toastConfig) +internal extension ProHUD.Configuration.Toast { + var loadSubviews: (ProHUD.Toast) -> Void { + return privLoadSubviews + } + var reloadData: (ProHUD.Toast) -> Void { + return privReloadData } } + +fileprivate var privLoadSubviews: (ProHUD.Toast) -> Void = { + return { (vc) in + debug(vc, "loadSubviews") + vc.view.tintColor = cfg.toast.tintColor + vc.view.addSubview(vc.titleLabel) + vc.view.addSubview(vc.bodyLabel) + vc.view.addSubview(vc.imageView) + } +}() + +fileprivate var privReloadData: (ProHUD.Toast) -> Void = { + return { (vc) in + debug(vc, "reloadData") + let config = cfg.toast + let scene = vc.vm.scene + // 设置数据 + let imgStr: String + switch vc.vm.scene { + case .success: + imgStr = "ProHUDSuccess" + case .warning: + imgStr = "ProHUDWarning" + case .error: + imgStr = "ProHUDError" + case .loading: + imgStr = "ProHUDLoading" + case .confirm: + imgStr = "ProHUDMessage" + case .delete: + imgStr = "ProHUDTrash" + default: + imgStr = "ProHUDMessage" + } + let img = vc.vm.icon ?? ProHUD.image(named: imgStr) + vc.imageView.image = img + vc.titleLabel.textColor = cfg.primaryLabelColor + vc.titleLabel.text = vc.vm.title + vc.bodyLabel.textColor = cfg.secondaryLabelColor + vc.bodyLabel.text = vc.vm.message + + // 更新布局 + vc.imageView.snp.makeConstraints { (mk) in + mk.top.equalToSuperview().offset(config.padding) + mk.leading.equalToSuperview().offset(config.padding) + mk.bottom.lessThanOrEqualToSuperview().offset(-config.padding) + mk.width.height.equalTo(config.iconSize) + } + vc.titleLabel.snp.makeConstraints { (mk) in + mk.top.equalToSuperview().offset(config.padding) + mk.leading.equalTo(vc.imageView.snp.trailing).offset(config.margin) + mk.leading.greaterThanOrEqualToSuperview().offset(config.padding) + mk.trailing.equalToSuperview().offset(-config.padding) + } + vc.bodyLabel.snp.makeConstraints { (mk) in + mk.top.equalTo(vc.titleLabel.snp.bottom).offset(config.margin) + mk.leading.trailing.equalTo(vc.titleLabel) + mk.bottom.lessThanOrEqualToSuperview().offset(-config.padding) + } + + vc.view.layoutIfNeeded() + } +}() diff --git a/ProHUD/Toast/ToastController.swift b/ProHUD/Toast/ToastController.swift index 966f2cd..5228e5c 100644 --- a/ProHUD/Toast/ToastController.swift +++ b/ProHUD/Toast/ToastController.swift @@ -24,20 +24,20 @@ public extension ProHUD { /// 标题 internal lazy var titleLabel: UILabel = { let lb = UILabel() - lb.textColor = UIColorForPrimaryLabel - lb.font = toastConfig.titleFont + lb.textColor = cfg.primaryLabelColor + lb.font = cfg.toast.titleFont lb.textAlignment = .justified - lb.numberOfLines = toastConfig.titleMaxLines + lb.numberOfLines = cfg.toast.titleMaxLines return lb }() /// 正文 internal lazy var bodyLabel: UILabel = { let lb = UILabel() - lb.textColor = UIColorForSecondaryLabel - lb.font = toastConfig.bodyFont + lb.textColor = cfg.secondaryLabelColor + lb.font = cfg.toast.bodyFont lb.textAlignment = .justified - lb.numberOfLines = toastConfig.bodyMaxLines + lb.numberOfLines = cfg.toast.bodyMaxLines return lb }() @@ -50,7 +50,7 @@ public extension ProHUD { vev.effect = UIBlurEffect.init(style: .extraLight) } vev.layer.masksToBounds = true - vev.layer.cornerRadius = toastConfig.cornerRadius + vev.layer.cornerRadius = cfg.toast.cornerRadius return vev }() @@ -84,9 +84,8 @@ public extension ProHUD { } // 布局 - toastConfig.loadSubviews(self) - toastConfig.reloadData(self) - toastConfig.layoutSubviews(self) + cfg.toast.loadSubviews(self) + cfg.toast.reloadData(self) // 点击 let tap = UITapGestureRecognizer(target: self, action: #selector(privDidTapped(_:))) @@ -137,28 +136,6 @@ public extension ProHUD { return self } -// internal func updateFrame() { -// let config = toastConfig -// var f = UIScreen.main.bounds -// contentStack.frame.size.width = CGFloat.minimum(f.width - 4 * config.margin, config.maxWidth) -// titleLabel?.sizeToFit() -// messageLabel?.sizeToFit() -// contentStack.layoutIfNeeded() -// f.size.width = contentStack.frame.size.width -// f.size.height = (textStack.arrangedSubviews.last?.frame.maxY ?? 0) + config.margin -// debugPrint(f) -// func updateFrame(_ frame: CGRect) -> CGRect { -// return CGRect(origin: CGPoint(x: config.margin, y: config.margin), size: frame.size) -// } -// func superBounds(_ frame: CGRect) -> CGRect { -// return CGRect(x: 0, y: 0, width: frame.width + 2 * config.margin, height: frame.height + 2 * config.margin) -// } -// contentStack.frame = updateFrame(f) -// contentView.frame = superBounds(f) -// view.frame = superBounds(f) -// window?.frame = superBounds(f) -// hud.updateToastsLayout() -// } // MARK: 设置函数 @@ -200,8 +177,7 @@ public extension ProHUD { vm.title = title vm.message = message vm.icon = icon - toastConfig.reloadData(self) - toastConfig.layoutSubviews(self) + cfg.toast.reloadData(self) return self } @@ -248,7 +224,7 @@ public extension ProHUD { @discardableResult func show(_ toast: Toast) -> Toast { - let config = toastConfig + let config = cfg.toast let isNew: Bool if toast.window == nil { let w = ToastWindow(frame: .zero) @@ -369,7 +345,7 @@ internal extension ProHUD { func f() { let top = Inspire.shared.screen.updatedSafeAreaInsets.top for (i, e) in toasts.enumerated() { - let config = toastConfig + let config = cfg.toast if let window = e.window { var y = window.frame.origin.y if i == 0 { @@ -411,7 +387,7 @@ internal extension ProHUD { } else if toasts.count == 1 { toasts.removeAll() } else { - debugPrint("漏洞:已经没有toast了") + debug("漏洞:已经没有toast了") } }