ProHUD/ProHUD/Alert/AlertConfig.swift

347 lines
12 KiB
Swift
Raw 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
2019-08-08 09:25:28 +08:00
import Inspire
2019-07-31 17:40:39 +08:00
public extension ProHUD.Configuration {
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-02 13:55:23 +08:00
// MARK:
/// default
public var tintColor: UIColor?
///
2019-07-31 17:40:39 +08:00
public var iconSize = CGSize(width: 48, height: 48)
2019-08-02 13:55:23 +08:00
// MARK:
///
public var titleFont = UIFont.boldSystemFont(ofSize: 22)
///
public var titleMaxLines = Int(1)
2019-07-31 21:08:25 +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(5)
// MARK:
///
public var buttonFont = UIFont.boldSystemFont(ofSize: 18)
// MARK:
2019-08-03 17:48:37 +08:00
2019-07-31 17:40:39 +08:00
///
2019-08-03 17:48:37 +08:00
/// - Parameter callback:
public mutating func loadSubviews(_ callback: @escaping (ProHUD.Alert) -> Void) {
privLoadSubviews = callback
}
2019-07-31 17:40:39 +08:00
///
2019-08-03 17:48:37 +08:00
/// - Parameter callback:
public mutating func reloadData(_ callback: @escaping (ProHUD.Alert) -> Void) {
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:
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
}
2019-08-08 19:29:03 +08:00
var setupDefaultDuration: (ProHUD.Alert) -> Void {
return { (vc) in
//
if let t = vc.model.duration, t > 0 {
if vc.buttonEvents.count > 0 {
vc.duration(nil)
}
} else if vc.model.duration == nil && vc.model.scene != .loading {
//
vc.duration(2)
}
}
}
var reloadStack: (ProHUD.Alert) -> Void {
return { (vc) in
if vc.textStack.arrangedSubviews.count > 0 {
vc.contentStack.addArrangedSubview(vc.textStack)
} else {
vc.textStack.removeFromSuperview()
}
if vc.actionStack.arrangedSubviews.count > 0 {
vc.contentStack.addArrangedSubview(vc.actionStack)
} else {
vc.actionStack.removeFromSuperview()
}
}
}
2019-08-03 17:48:37 +08:00
}
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
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
}
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
2019-08-05 11:18:25 +08:00
switch vc.model.scene {
2019-08-03 17:48:37 +08:00
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"
}
2019-08-05 11:18:25 +08:00
let img = vc.model.icon ?? ProHUD.image(named: imgStr)
2019-08-03 17:48:37 +08:00
if let imgv = vc.imageView {
imgv.image = img
} else {
let icon = UIImageView(image: img)
vc.contentStack.addArrangedSubview(icon)
2019-08-03 18:03:20 +08:00
icon.contentMode = .scaleAspectFit
2019-08-03 17:48:37 +08:00
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)
2019-08-03 18:03:20 +08:00
mk.width.equalTo(config.iconSize.width)
mk.height.equalTo(config.iconSize.height)
2019-08-03 17:48:37 +08:00
}
vc.imageView = icon
}
2019-08-08 19:29:03 +08:00
vc.imageView?.layer.removeAllAnimations()
2019-08-03 17:48:37 +08:00
// text
2019-08-05 11:18:25 +08:00
if vc.model.title?.count ?? 0 > 0 || vc.model.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-05 11:18:25 +08:00
if vc.model.title?.count ?? 0 > 0 {
2019-08-03 17:48:37 +08:00
if let lb = vc.titleLabel {
2019-08-05 11:18:25 +08:00
lb.text = vc.model.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-05 11:18:25 +08:00
title.text = vc.model.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-05 11:18:25 +08:00
if vc.model.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-05 11:18:25 +08:00
if vc.model.message?.count ?? 0 > 0 {
if let lb = vc.bodyLabel {
lb.text = vc.model.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-05 11:18:25 +08:00
body.text = vc.model.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-05 11:18:25 +08:00
if vc.model.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()
}
if vc.actionStack.superview != nil {
if isFirstLayout {
vc.contentStack.addArrangedSubview(vc.actionStack)
} else {
vc.actionStack.transform = .init(scaleX: 1, y: 0.001)
2019-08-02 13:55:23 +08:00
UIView.animateForAlert {
2019-08-03 17:48:37 +08:00
vc.contentStack.addArrangedSubview(vc.actionStack)
vc.view.layoutIfNeeded()
2019-07-31 17:40:39 +08:00
}
2019-08-03 17:48:37 +08:00
}
// 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
2019-07-31 17:40:39 +08:00
}
}
2019-08-03 17:48:37 +08:00
2019-07-31 17:40:39 +08:00
}
2019-08-03 17:48:37 +08:00
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()
}
2019-07-31 17:40:39 +08:00
}
2019-08-08 19:29:03 +08:00
2019-07-31 17:40:39 +08:00
}
2019-08-03 17:48:37 +08:00
}()
2019-07-31 21:08:25 +08:00
2019-08-03 17:48:37 +08:00
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("点击了隐藏")
2019-08-05 11:18:25 +08:00
vc?.model.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