ProHUD/Source/Alert/AlertConfig.swift

341 lines
12 KiB
Swift
Raw Permalink Normal View History

2019-07-31 17:40:39 +08:00
//
2019-08-03 17:48:37 +08:00
// cfg.alert.swift
2019-07-31 17:40:39 +08:00
// ProHUD
//
// Created by xaoxuu on 2019/7/29.
// Copyright © 2019 Titan Studio. All rights reserved.
//
import UIKit
import SnapKit
public extension UIWindow.Level {
2021-07-20 16:04:39 +08:00
static let alertForProHUD = UIWindow.Level.alert - 1
}
2019-07-31 17:40:39 +08:00
public extension ProHUD.Configuration {
2019-08-12 17:59:40 +08:00
struct Alert {
2019-08-02 13:55:23 +08:00
// MARK:
2019-07-31 17:40:39 +08:00
/// iPad
public var maxWidth = CGFloat(400)
///
public var cornerRadius = CGFloat(16)
2019-08-02 13:55:23 +08:00
///
2019-07-31 17:40:39 +08:00
public var margin = CGFloat(8)
2019-08-02 13:55:23 +08:00
///
2019-07-31 17:40:39 +08:00
public var padding = CGFloat(16)
2019-08-12 15:02:36 +08:00
///
2019-08-02 13:55:23 +08:00
public var tintColor: UIColor?
2019-08-12 15:02:36 +08:00
// MARK:
2019-08-02 13:55:23 +08:00
///
2019-07-31 17:40:39 +08:00
public var iconSize = CGSize(width: 48, height: 48)
2019-08-09 18:02:41 +08:00
2019-08-02 13:55:23 +08:00
// MARK:
///
public var titleFont = UIFont.boldSystemFont(ofSize: 22)
///
public var titleMaxLines = Int(5)
2019-07-31 21:08:25 +08:00
2019-08-12 15:02:36 +08:00
///
2019-08-02 13:55:23 +08:00
public var boldTextFont = UIFont.boldSystemFont(ofSize: 18)
///
public var bodyFont = UIFont.systemFont(ofSize: 17)
///
public var bodyMaxLines = Int(20)
2019-08-02 13:55:23 +08:00
// MARK:
///
public var buttonFont = UIFont.boldSystemFont(ofSize: 18)
// MARK:
2019-08-03 17:48:37 +08:00
2019-08-09 18:02:41 +08:00
///
public func reloadData(_ callback: @escaping (ProHUD.Alert) -> Void) {
2019-08-03 17:48:37 +08:00
privReloadData = callback
}
/// 退
2019-08-08 09:25:28 +08:00
public var forceQuitTimer = TimeInterval(30)
2019-08-03 17:48:37 +08:00
/// 退
public var forceQuitTitle = "隐藏窗口"
/// 退
/// - Parameter callback:
2020-06-22 13:27:54 +08:00
public func loadHideButton(_ callback: @escaping (ProHUD.Alert) -> Void) {
privLoadHideButton = callback
2019-08-03 17:48:37 +08:00
}
2019-08-09 18:02:41 +08:00
2019-08-03 17:48:37 +08:00
}
}
2019-08-09 18:02:41 +08:00
// MARK: -
2021-07-20 16:04:39 +08:00
extension ProHUD.Configuration.Alert {
2019-08-12 17:59:40 +08:00
2019-08-03 17:48:37 +08:00
var reloadData: (ProHUD.Alert) -> Void {
return privReloadData
}
2019-08-12 17:59:40 +08:00
2019-08-03 17:48:37 +08:00
}
2019-08-09 18:02:41 +08:00
// MARK: -
fileprivate var privLayoutContentView: (ProHUD.Alert) -> Void = {
2019-08-03 17:48:37 +08:00
return { (vc) in
if vc.contentView.superview == nil {
vc.view.addSubview(vc.contentView)
vc.contentView.layer.masksToBounds = true
vc.contentView.layer.cornerRadius = cfg.alert.cornerRadius
2019-08-08 09:25:28 +08:00
let maxWidth = CGFloat.maximum(CGFloat.minimum(UIScreen.main.bounds.width * 0.68, cfg.alert.maxWidth), 268)
2019-08-03 17:48:37 +08:00
vc.contentView.snp.makeConstraints { (mk) in
mk.center.equalToSuperview()
2019-08-08 09:25:28 +08:00
mk.width.lessThanOrEqualTo(maxWidth)
2019-08-03 17:48:37 +08:00
}
2019-08-09 18:02:41 +08:00
}
if vc.contentStack.superview == nil {
vc.contentView.contentView.addSubview(vc.contentStack)
vc.contentStack.spacing = cfg.alert.margin + cfg.alert.padding
2019-08-03 17:48:37 +08:00
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)
}
}
}
}()
2019-08-09 18:02:41 +08:00
fileprivate var privUpdateImage: (ProHUD.Alert) -> Void = {
return { (vc) in
let config = cfg.alert
2019-08-13 11:32:27 +08:00
let img = vc.vm.icon ?? vc.vm.scene.image
vc.imageView.image = img
vc.contentStack.addArrangedSubview(vc.imageView)
vc.imageView.contentMode = .scaleAspectFit
vc.imageView.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)
mk.width.equalTo(config.iconSize.width)
mk.height.equalTo(config.iconSize.height)
2019-08-03 17:48:37 +08:00
}
2020-06-24 11:28:54 +08:00
//
vc.stopRotate(vc.animateLayer)
vc.animateLayer = nil
vc.animation = nil
2020-06-24 11:12:42 +08:00
//
2020-06-22 16:34:21 +08:00
vc.progressView?.removeFromSuperview()
2019-08-09 18:02:41 +08:00
}
}()
fileprivate var privUpdateTextStack: (ProHUD.Alert) -> Void = {
return { (vc) in
let config = cfg.alert
2019-08-13 11:32:27 +08:00
if vc.vm.title == nil {
vc.vm.title = vc.vm.scene.title
}
if vc.vm.message == nil {
vc.vm.message = vc.vm.scene.message
}
2019-08-09 18:02:41 +08:00
if vc.vm.title?.count ?? 0 > 0 || vc.vm.message?.count ?? 0 > 0 {
2019-08-03 17:48:37 +08:00
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)
2019-08-08 09:25:28 +08:00
if UIScreen.main.bounds.width < 414 {
mk.leading.greaterThanOrEqualTo(vc.contentView).offset(config.padding*1.5)
mk.trailing.lessThanOrEqualTo(vc.contentView).offset(-config.padding*1.5)
} else {
mk.leading.greaterThanOrEqualTo(vc.contentView).offset(config.padding*2)
mk.trailing.lessThanOrEqualTo(vc.contentView).offset(-config.padding*2)
}
2019-08-03 17:48:37 +08:00
}
2019-08-09 18:02:41 +08:00
if vc.vm.title?.count ?? 0 > 0 {
2019-08-03 17:48:37 +08:00
if let lb = vc.titleLabel {
2019-08-09 18:02:41 +08:00
lb.text = vc.vm.title
2019-07-31 17:40:39 +08:00
} else {
2019-08-03 17:48:37 +08:00
let title = UILabel()
title.textAlignment = .center
title.numberOfLines = config.titleMaxLines
title.textColor = cfg.primaryLabelColor
2019-08-09 18:02:41 +08:00
title.text = vc.vm.title
2019-08-03 17:48:37 +08:00
vc.textStack.addArrangedSubview(title)
vc.titleLabel = title
2019-07-31 17:40:39 +08:00
}
2019-08-09 18:02:41 +08:00
if vc.vm.message?.count ?? 0 > 0 {
2019-08-03 17:48:37 +08:00
// message
vc.titleLabel?.font = config.titleFont
2019-07-31 17:40:39 +08:00
} else {
2019-08-03 17:48:37 +08:00
// message
vc.titleLabel?.font = config.boldTextFont
2019-07-31 17:40:39 +08:00
}
2019-08-03 17:48:37 +08:00
} else {
vc.titleLabel?.removeFromSuperview()
}
2019-08-09 18:02:41 +08:00
if vc.vm.message?.count ?? 0 > 0 {
2019-08-05 11:18:25 +08:00
if let lb = vc.bodyLabel {
2019-08-09 18:02:41 +08:00
lb.text = vc.vm.message
2019-07-31 17:40:39 +08:00
} else {
2019-08-03 17:48:37 +08:00
let body = UILabel()
body.textAlignment = .center
body.font = config.bodyFont
body.numberOfLines = config.bodyMaxLines
body.textColor = cfg.secondaryLabelColor
2019-08-09 18:02:41 +08:00
body.text = vc.vm.message
2019-08-03 17:48:37 +08:00
vc.textStack.addArrangedSubview(body)
2019-08-05 11:18:25 +08:00
vc.bodyLabel = body
2019-07-31 17:40:39 +08:00
}
2019-08-09 18:02:41 +08:00
if vc.vm.title?.count ?? 0 > 0 {
2019-08-03 17:48:37 +08:00
// title
2019-08-05 11:18:25 +08:00
vc.bodyLabel?.font = config.bodyFont
2019-07-31 17:40:39 +08:00
} else {
2019-08-03 17:48:37 +08:00
// title
2019-08-05 11:18:25 +08:00
vc.bodyLabel?.font = config.boldTextFont
2019-07-31 17:40:39 +08:00
}
2019-08-03 17:48:37 +08:00
} else {
2019-08-05 11:18:25 +08:00
vc.bodyLabel?.removeFromSuperview()
2019-07-31 17:40:39 +08:00
}
2019-08-03 17:48:37 +08:00
} else {
vc.textStack.removeFromSuperview()
}
2019-08-09 18:02:41 +08:00
vc.textStack.layoutIfNeeded()
}
}()
fileprivate var privUpdateActionStack: (ProHUD.Alert) -> Void = {
return { (vc) in
let config = cfg.alert
2019-08-12 17:59:40 +08:00
if vc.actionStack.arrangedSubviews.count > 0 {
2019-08-09 18:02:41 +08:00
//
vc.contentStack.addArrangedSubview(vc.actionStack)
2019-08-03 17:48:37 +08:00
// iPad
2019-08-12 17:59:40 +08:00
if isPortrait == false && vc.actionStack.arrangedSubviews.count < 4 {
2019-08-03 17:48:37 +08:00
vc.actionStack.axis = .horizontal
vc.actionStack.alignment = .fill
vc.actionStack.distribution = .fillEqually
}
2019-08-09 18:02:41 +08:00
vc.actionStack.snp.makeConstraints { (mk) in
2019-08-03 17:48:37 +08:00
mk.width.greaterThanOrEqualTo(200)
mk.leading.trailing.equalToSuperview()
}
} else {
2019-08-09 18:02:41 +08:00
//
for v in vc.actionStack.arrangedSubviews {
v.removeFromSuperview()
2019-08-03 17:48:37 +08:00
}
2019-08-09 18:02:41 +08:00
vc.actionStack.removeFromSuperview()
2019-07-31 17:40:39 +08:00
}
2019-08-09 18:02:41 +08:00
vc.actionStack.layoutIfNeeded()
2019-07-31 17:40:39 +08:00
}
2019-08-03 17:48:37 +08:00
}()
2019-07-31 21:08:25 +08:00
2020-06-22 13:27:54 +08:00
fileprivate var privLoadHideButton: (ProHUD.Alert) -> Void = {
2019-08-03 17:48:37 +08:00
return { (vc) in
debug(vc, "showNavButtons")
let config = cfg.alert
2020-06-22 13:27:54 +08:00
let btn = ProHUD.Alert.Button.createHideButton()
2019-08-03 17:48:37 +08:00
btn.setTitle(cfg.alert.forceQuitTitle, for: .normal)
2019-08-12 15:02:36 +08:00
let bg = createBlurView()
2019-08-03 17:48:37 +08:00
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
2019-08-09 18:02:41 +08:00
debug("点击了【\(config.forceQuitTitle)")
vc?.vm.forceQuitCallback?()
2019-08-03 18:03:20 +08:00
vc?.pop()
2019-08-03 17:48:37 +08:00
}
2019-07-31 21:08:25 +08:00
}
2019-08-03 17:48:37 +08:00
}()
2019-08-08 19:29:03 +08:00
2019-08-09 18:02:41 +08:00
///
fileprivate var privReloadData: (ProHUD.Alert) -> Void = {
return { (vc) in
debug(vc, "reloadData")
let config = cfg.alert
let isFirstLayout: Bool
if vc.contentView.superview == nil {
isFirstLayout = true
//
privLayoutContentView(vc)
} else {
isFirstLayout = false
}
//
privUpdateImage(vc)
//
privUpdateTextStack(vc)
//
privUpdateActionStack(vc)
vc.contentStack.layoutIfNeeded()
vc.contentView.layoutIfNeeded()
//
if isFirstLayout {
vc.view.layoutIfNeeded()
vc.imageView.transform = .init(scaleX: 0.75, y: 0.75)
2019-08-09 18:02:41 +08:00
UIView.animateForAlert {
vc.view.layoutIfNeeded()
vc.imageView.transform = .identity
2019-08-09 18:02:41 +08:00
}
} else {
UIView.animateForAlert {
vc.view.layoutIfNeeded()
}
}
2019-08-12 17:59:40 +08:00
//
vc.vm.updateDuration()
2019-08-09 18:02:41 +08:00
2020-06-23 20:16:05 +08:00
// id .rotate
if vc.vm.scene.identifier.contains(".rotate") {
vc.startRotate()
}
2020-06-22 13:27:54 +08:00
//
vc.vm.hideTimerBlock?.cancel()
2019-08-09 18:02:41 +08:00
if vc.buttonEvents.count == 0 {
2020-06-22 13:27:54 +08:00
vc.vm.hideTimerBlock = DispatchWorkItem(block: { [weak vc] in
2019-08-09 18:02:41 +08:00
if let vc = vc {
if vc.buttonEvents.count == 0 {
2020-06-22 13:27:54 +08:00
privLoadHideButton(vc)
2019-08-09 18:02:41 +08:00
}
}
})
2020-06-22 13:27:54 +08:00
DispatchQueue.main.asyncAfter(deadline: .now() + config.forceQuitTimer, execute: vc.vm.hideTimerBlock!)
2019-08-09 18:02:41 +08:00
} else {
2020-06-22 13:27:54 +08:00
vc.vm.hideTimerBlock = nil
2019-08-09 18:02:41 +08:00
}
}
}()