代码优化
|
@ -91,20 +91,34 @@ class AlertVC: ListVC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list.add(title: "图标 + 文字 + 按钮") { section in
|
list.add(title: "图标 + 文字 + 按钮") { section in
|
||||||
section.add(title: "图标 + 一段文字 + 自定义浅色按钮") {
|
section.add(title: "操作成功") {
|
||||||
Alert(.confirm) { alert in
|
Alert(.success(3).title("操作成功").message("这条消息将在3s后消失")).push()
|
||||||
alert.vm.title = "自定义浅色按钮"
|
}
|
||||||
|
section.add(title: "操作失败") {
|
||||||
|
Alert { alert in
|
||||||
|
alert.vm = .error.title("操作失败").message("请稍后重试")
|
||||||
|
alert.add(action: "取消", style: .gray)
|
||||||
|
alert.add(action: "重试")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
section.add(title: "警告") {
|
||||||
|
Alert(.warning.message("电量不足,请立即充电")) { alert in
|
||||||
|
let btn = alert.add(action: "我知道了", style: .filled(color: UIColor.systemYellow))
|
||||||
|
btn.setTitleColor(.black, for: .normal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
section.add(title: "确认选择") {
|
||||||
|
Alert(.confirm.title("请选择颜色")) { alert in
|
||||||
alert.add(action: "红色", style: .light(color: .systemRed))
|
alert.add(action: "红色", style: .light(color: .systemRed))
|
||||||
alert.add(action: "蓝色", style: .light(color: .systemBlue))
|
alert.add(action: "蓝色", style: .light(color: .systemBlue))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
section.add(title: "图标 + 标题 + 正文 + 自定义深色按钮") {
|
section.add(title: "确认删除") {
|
||||||
Alert(.note) { alert in
|
Alert(.delete) { alert in
|
||||||
alert.vm.title = "自定义深色按钮"
|
alert.vm.title = "确认删除"
|
||||||
alert.vm.message = "这是一段正文,长度超出最大宽度时会自动换行"
|
alert.vm.message = "此操作无法撤销"
|
||||||
alert.add(action: "橙色", style: .filled(color: .systemOrange))
|
alert.add(action: "取消", style: .gray)
|
||||||
alert.add(action: "粉色", style: .filled(color: .systemPink))
|
alert.add(action: "删除", style: .destructive)
|
||||||
alert.add(action: "默认灰色", style: .gray)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -213,9 +227,13 @@ class AlertVC: ListVC {
|
||||||
let vc = UIViewController()
|
let vc = UIViewController()
|
||||||
vc.title = "页面"
|
vc.title = "页面"
|
||||||
vc.view.backgroundColor = .systemYellow
|
vc.view.backgroundColor = .systemYellow
|
||||||
let alert = Alert(.loading.title("正在加载").message("这个弹窗被放在指定的容器中"))
|
let alert = Alert(.loading.title("正在加载").message("这个弹窗被放在指定容器中"))
|
||||||
|
alert.add(action: "返回上一页") { alert in
|
||||||
|
vc.dismiss(animated: true)
|
||||||
|
}
|
||||||
alert.config.enableShadow = false
|
alert.config.enableShadow = false
|
||||||
self?.present(vc, animated: true)
|
self?.present(vc, animated: true)
|
||||||
|
vc.addChild(alert)
|
||||||
vc.view.addSubview(alert.view)
|
vc.view.addSubview(alert.view)
|
||||||
alert.view.snp.makeConstraints { make in
|
alert.view.snp.makeConstraints { make in
|
||||||
make.edges.equalToSuperview()
|
make.edges.equalToSuperview()
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "prohud.trash@2x.png",
|
"filename" : "demo.message@2x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "prohud.trash@3x.png",
|
"filename" : "demo.message@3x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
}
|
}
|
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 3.8 KiB |
|
@ -5,12 +5,12 @@
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "prohud.note@2x.png",
|
"filename" : "demo.note@2x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "prohud.note@3x.png",
|
"filename" : "demo.note@3x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
}
|
}
|
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 3.7 KiB |
|
@ -5,12 +5,12 @@
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "prohud.message@2x.png",
|
"filename" : "demo.questionmark@2x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "prohud.message@3x.png",
|
"filename" : "demo.questionmark@3x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
}
|
}
|
BIN
PHDemo/PHDemo/Assets.xcassets/demo.questionmark.imageset/demo.questionmark@2x.png
vendored
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
PHDemo/PHDemo/Assets.xcassets/demo.questionmark.imageset/demo.questionmark@3x.png
vendored
Normal file
After Width: | Height: | Size: 7.3 KiB |
|
@ -5,12 +5,12 @@
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "prohud.trash@2x.png",
|
"filename" : "demo.trash@2x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "prohud.trash@3x.png",
|
"filename" : "demo.trash@3x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
}
|
}
|
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 3.8 KiB |
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"images" : [
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "prohud.rainbow.circle@2x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "prohud.rainbow.circle@3x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "3x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info" : {
|
|
||||||
"author" : "xcode",
|
|
||||||
"version" : 1
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 6.5 KiB |
|
@ -15,17 +15,30 @@ public extension ViewModel {
|
||||||
// static var note: ViewModel {
|
// static var note: ViewModel {
|
||||||
// ViewModel(icon: UIImage(named: "prohud.note"))
|
// ViewModel(icon: UIImage(named: "prohud.note"))
|
||||||
// }
|
// }
|
||||||
|
// MARK: note
|
||||||
|
static var note: ViewModel {
|
||||||
|
.init(icon: UIImage(named: "demo.note"))
|
||||||
|
}
|
||||||
|
static func note(_ seconds: TimeInterval) -> ViewModel {
|
||||||
|
.init(icon: UIImage(named: "demo.note"), duration: seconds)
|
||||||
|
}
|
||||||
static var msg: ViewModel {
|
static var msg: ViewModel {
|
||||||
ViewModel(icon: UIImage(inProHUD: "prohud.message"))
|
ViewModel(icon: UIImage(named: "demo.message"))
|
||||||
}
|
}
|
||||||
static func msg(_ seconds: TimeInterval) -> ViewModel {
|
static func msg(_ seconds: TimeInterval) -> ViewModel {
|
||||||
ViewModel(icon: UIImage(inProHUD: "prohud.message"), duration: seconds)
|
ViewModel(icon: UIImage(named: "demo.message"), duration: seconds)
|
||||||
}
|
}
|
||||||
static var loading: ViewModel {
|
static var delete: ViewModel {
|
||||||
let obj = ViewModel(icon: UIImage(named: "prohud.rainbow.circle"))
|
ViewModel(icon: UIImage(named: "demo.trash"))
|
||||||
obj.rotation = .init(repeatCount: .infinity)
|
|
||||||
return obj
|
|
||||||
}
|
}
|
||||||
|
// MARK: confirm
|
||||||
|
static var confirm: ViewModel {
|
||||||
|
.init(icon: UIImage(named: "demo.questionmark"))
|
||||||
|
}
|
||||||
|
static func confirm(_ seconds: TimeInterval) -> ViewModel {
|
||||||
|
.init(icon: UIImage(named: "demo.questionmark"), duration: seconds)
|
||||||
|
}
|
||||||
|
|
||||||
// static func loading(_ seconds: TimeInterval) -> ViewModel {
|
// static func loading(_ seconds: TimeInterval) -> ViewModel {
|
||||||
// let obj = ViewModel(icon: UIImage(named: "prohud.rainbow.circle"), duration: seconds)
|
// let obj = ViewModel(icon: UIImage(named: "prohud.rainbow.circle"), duration: seconds)
|
||||||
// obj.rotation = .init(repeatCount: .infinity)
|
// obj.rotation = .init(repeatCount: .infinity)
|
||||||
|
|
|
@ -18,6 +18,14 @@ class ToastVC: ListVC {
|
||||||
header.titleLabel.text = "ProHUD.Toast"
|
header.titleLabel.text = "ProHUD.Toast"
|
||||||
header.detailLabel.text = message
|
header.detailLabel.text = message
|
||||||
|
|
||||||
|
Toast.Configuration.shared { config in
|
||||||
|
config.contentViewMask { mask in
|
||||||
|
mask.backgroundColor = .clear
|
||||||
|
mask.effect = UIBlurEffect(style: .systemChromeMaterial)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
list.add(title: "默认布局") { section in
|
list.add(title: "默认布局") { section in
|
||||||
section.add(title: "标题 + 正文") {
|
section.add(title: "标题 + 正文") {
|
||||||
Toast(.title(title).message(message)).push()
|
Toast(.title(title).message(message)).push()
|
||||||
|
@ -29,7 +37,6 @@ class ToastVC: ListVC {
|
||||||
let s1 = "正在加载"
|
let s1 = "正在加载"
|
||||||
let s2 = "这条通知4s后消失"
|
let s2 = "这条通知4s后消失"
|
||||||
let toast = Toast(.loading(4).title(s1).message(s2))
|
let toast = Toast(.loading(4).title(s1).message(s2))
|
||||||
toast.identifier = "loading"
|
|
||||||
toast.push()
|
toast.push()
|
||||||
toast.update(progress: 0)
|
toast.update(progress: 0)
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||||
|
@ -39,8 +46,8 @@ class ToastVC: ListVC {
|
||||||
toast.update(progress: 1)
|
toast.update(progress: 1)
|
||||||
}
|
}
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) {
|
||||||
Toast.find(identifier: "loading") { toast in
|
toast.update { toast in
|
||||||
toast.vm = .success(2).title("加载成功").message("这条通知2s后消失")
|
toast.vm = .success(10).title("加载成功").message("这条通知10s后消失")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,13 +57,13 @@ class ToastVC: ListVC {
|
||||||
}
|
}
|
||||||
|
|
||||||
list.add(title: "事件管理") { section in
|
list.add(title: "事件管理") { section in
|
||||||
section.add(title: "全局点击事件") {
|
section.add(title: "点击事件") {
|
||||||
let title = "您收到了一条消息"
|
let title = "您收到了一条消息"
|
||||||
let message = "这条消息5s后消失,点击回复"
|
let message = "点击通知横幅任意处即可回复"
|
||||||
Toast(.msg(5).title(title).message(message)) { toast in
|
Toast(.msg.title(title).message(message)) { toast in
|
||||||
toast.onTapped { toast in
|
toast.onTapped { toast in
|
||||||
toast.pop()
|
toast.pop()
|
||||||
testAlert()
|
Alert(.success(1).message("操作成功")).push()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,8 +94,11 @@ class ToastVC: ListVC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
toast.add(action: "同意") { toast in
|
toast.add(action: "同意") { toast in
|
||||||
Alert.find(identifier: "Dracarys")?.pop()
|
Alert.find(identifier: "Dracarys", update: { alert in
|
||||||
|
alert.pop()
|
||||||
|
})
|
||||||
toast.pop()
|
toast.pop()
|
||||||
|
Alert(.success(1).message("Good choice!")).push()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +134,9 @@ class ToastVC: ListVC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
section.add(title: "移除指定实例") {
|
section.add(title: "移除指定实例") {
|
||||||
Toast.find(identifier: "loading")?.pop()
|
Toast.find(identifier: "loading") { toast in
|
||||||
|
toast.pop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 4.7 KiB |
|
@ -33,8 +33,13 @@ public class Alert: ProHUD.Controller {
|
||||||
return stack
|
return stack
|
||||||
}()
|
}()
|
||||||
|
|
||||||
/// 图片
|
/// 图标
|
||||||
public var imageView = UIImageView()
|
public lazy var imageView: UIImageView = {
|
||||||
|
let imgv = UIImageView()
|
||||||
|
imgv.contentMode = .scaleAspectFit
|
||||||
|
imgv.tintColor = view.tintColor
|
||||||
|
return imgv
|
||||||
|
}()
|
||||||
|
|
||||||
/// 标题
|
/// 标题
|
||||||
public lazy var titleLabel: UILabel = {
|
public lazy var titleLabel: UILabel = {
|
||||||
|
|
|
@ -29,6 +29,7 @@ extension Alert: DefaultLayout {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// default layout
|
// default layout
|
||||||
|
|
||||||
// 更新图片
|
// 更新图片
|
||||||
setupImageView()
|
setupImageView()
|
||||||
|
|
||||||
|
@ -53,14 +54,6 @@ extension Alert: DefaultLayout {
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// id 包含 .rotate 的会自动旋转
|
|
||||||
if let rotation = vm.rotation {
|
|
||||||
startRotate(rotation)
|
|
||||||
}
|
|
||||||
// 设置持续时间
|
|
||||||
vm.timeoutHandler = DispatchWorkItem(block: { [weak self] in
|
|
||||||
self?.pop()
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,16 +126,6 @@ extension Alert: DefaultLayout {
|
||||||
extension Alert {
|
extension Alert {
|
||||||
|
|
||||||
func setupImageView() {
|
func setupImageView() {
|
||||||
guard let icon = vm.icon else { return }
|
|
||||||
imageView.image = icon
|
|
||||||
contentStack.insertArrangedSubview(imageView, at: 0)
|
|
||||||
imageView.contentMode = .scaleAspectFit
|
|
||||||
imageView.snp.remakeConstraints { (mk) in
|
|
||||||
mk.top.left.greaterThanOrEqualTo(contentView).inset(config.padding*2.25)
|
|
||||||
mk.right.bottom.lessThanOrEqualTo(contentView).inset(config.padding*2.25)
|
|
||||||
mk.width.equalTo(config.iconSize.width)
|
|
||||||
mk.height.equalTo(config.iconSize.height)
|
|
||||||
}
|
|
||||||
// 移除动画
|
// 移除动画
|
||||||
stopRotate(animateLayer)
|
stopRotate(animateLayer)
|
||||||
animateLayer = nil
|
animateLayer = nil
|
||||||
|
@ -150,6 +133,28 @@ extension Alert {
|
||||||
|
|
||||||
// 移除进度
|
// 移除进度
|
||||||
progressView?.removeFromSuperview()
|
progressView?.removeFromSuperview()
|
||||||
|
|
||||||
|
if vm.icon != nil {
|
||||||
|
imageView.image = vm.icon
|
||||||
|
if imageView.superview == nil {
|
||||||
|
contentStack.insertArrangedSubview(imageView, at: 0)
|
||||||
|
imageView.snp.remakeConstraints { (mk) in
|
||||||
|
mk.top.left.greaterThanOrEqualTo(contentView).inset(config.padding*2.25)
|
||||||
|
mk.right.bottom.lessThanOrEqualTo(contentView).inset(config.padding*2.25)
|
||||||
|
mk.width.equalTo(config.iconSize.width)
|
||||||
|
mk.height.equalTo(config.iconSize.height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let rotation = vm.rotation {
|
||||||
|
startRotate(rotation)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if contentStack.arrangedSubviews.contains(imageView) {
|
||||||
|
contentStack.removeArrangedSubview(imageView)
|
||||||
|
}
|
||||||
|
imageView.removeFromSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
func setupTextStack() {
|
func setupTextStack() {
|
||||||
let titleCount = vm.title?.count ?? 0
|
let titleCount = vm.title?.count ?? 0
|
||||||
|
|
|
@ -85,7 +85,7 @@ extension Alert {
|
||||||
|
|
||||||
/// 更新HUD实例
|
/// 更新HUD实例
|
||||||
/// - Parameter callback: 实例更新代码
|
/// - Parameter callback: 实例更新代码
|
||||||
func update(handler: @escaping (_ alert: Alert) -> Void) {
|
public func update(handler: @escaping (_ alert: Alert) -> Void) {
|
||||||
handler(self)
|
handler(self)
|
||||||
reloadData()
|
reloadData()
|
||||||
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
||||||
|
@ -96,14 +96,12 @@ extension Alert {
|
||||||
/// 查找HUD实例
|
/// 查找HUD实例
|
||||||
/// - Parameter identifier: 唯一标识符
|
/// - Parameter identifier: 唯一标识符
|
||||||
/// - Returns: HUD实例
|
/// - Returns: HUD实例
|
||||||
public static func find(identifier: String, update handler: ((_ alert: Alert) -> Void)? = nil) -> Alert? {
|
@discardableResult public static func find(identifier: String, update handler: ((_ alert: Alert) -> Void)? = nil) -> [Alert] {
|
||||||
guard let vc = AlertWindow.alerts.last(where: { $0.identifier == identifier }) else {
|
let arr = AlertWindow.alerts.filter({ $0.identifier == identifier })
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if let handler = handler {
|
if let handler = handler {
|
||||||
vc.update(handler: handler)
|
arr.forEach({ $0.update(handler: handler) })
|
||||||
}
|
}
|
||||||
return vc
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ public class Configuration: NSObject {
|
||||||
|
|
||||||
// MARK: 图标样式
|
// MARK: 图标样式
|
||||||
/// 图标尺寸
|
/// 图标尺寸
|
||||||
public var iconSize = CGSize(width: 48, height: 48)
|
public var iconSize = CGSize(width: 44, height: 44)
|
||||||
|
|
||||||
// MARK: 文本样式
|
// MARK: 文本样式
|
||||||
/// 标题字体
|
/// 标题字体
|
||||||
|
|
|
@ -105,21 +105,14 @@ public extension ViewModel {
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: note
|
|
||||||
static var note: ViewModel {
|
|
||||||
.init(icon: UIImage(inProHUD: "prohud.note"))
|
|
||||||
}
|
|
||||||
static func note(_ seconds: TimeInterval) -> ViewModel {
|
|
||||||
.init(icon: UIImage(inProHUD: "prohud.note"), duration: seconds)
|
|
||||||
}
|
|
||||||
// MARK: loading
|
// MARK: loading
|
||||||
static var loading: ViewModel {
|
static var loading: ViewModel {
|
||||||
let obj = ViewModel(icon: UIImage(inProHUD: "prohud.rainbow.circle"))
|
let obj = ViewModel(icon: UIImage(inProHUD: "prohud.windmill"))
|
||||||
obj.rotation = .init(repeatCount: .infinity)
|
obj.rotation = .init(repeatCount: .infinity)
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
static func loading(_ seconds: TimeInterval) -> ViewModel {
|
static func loading(_ seconds: TimeInterval) -> ViewModel {
|
||||||
let obj = ViewModel(icon: UIImage(inProHUD: "prohud.rainbow.circle"), duration: seconds)
|
let obj = ViewModel(icon: UIImage(inProHUD: "prohud.windmill"), duration: seconds)
|
||||||
obj.rotation = .init(repeatCount: .infinity)
|
obj.rotation = .init(repeatCount: .infinity)
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
@ -148,12 +141,4 @@ public extension ViewModel {
|
||||||
static var failure: ViewModel { error }
|
static var failure: ViewModel { error }
|
||||||
static func failure(_ seconds: TimeInterval) -> ViewModel { error(seconds) }
|
static func failure(_ seconds: TimeInterval) -> ViewModel { error(seconds) }
|
||||||
|
|
||||||
// MARK: confirm
|
|
||||||
static var confirm: ViewModel {
|
|
||||||
.init(icon: UIImage(inProHUD: "prohud.questionmark"))
|
|
||||||
}
|
|
||||||
static func confirm(_ seconds: TimeInterval) -> ViewModel {
|
|
||||||
.init(icon: UIImage(inProHUD: "prohud.questionmark"), duration: seconds)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,13 +12,16 @@ extension LoadingAnimation {
|
||||||
/// 更新进度(如果需要显示进度,需要先调用一次 updateProgress(0) 来初始化)
|
/// 更新进度(如果需要显示进度,需要先调用一次 updateProgress(0) 来初始化)
|
||||||
/// - Parameter progress: 进度(0~1)
|
/// - Parameter progress: 进度(0~1)
|
||||||
public func update(progress: CGFloat) {
|
public func update(progress: CGFloat) {
|
||||||
|
guard isViewLoaded else { return }
|
||||||
guard let superview = imageView.superview else { return }
|
guard let superview = imageView.superview else { return }
|
||||||
if progressView == nil {
|
if progressView == nil {
|
||||||
let v = ProgressView()
|
let width = imageView.frame.size.width + ProgressView.lineWidth * 2
|
||||||
|
let v = ProgressView(frame: .init(origin: .zero, size: .init(width: width, height: width)))
|
||||||
superview.addSubview(v)
|
superview.addSubview(v)
|
||||||
|
v.tintColor = superview.tintColor
|
||||||
v.snp.remakeConstraints { (mk) in
|
v.snp.remakeConstraints { (mk) in
|
||||||
mk.center.equalTo(imageView)
|
mk.center.equalTo(imageView)
|
||||||
mk.width.height.equalTo(28)
|
mk.width.height.equalTo(width)
|
||||||
}
|
}
|
||||||
progressView = v
|
progressView = v
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,23 +12,41 @@ public class ProgressView: UIView {
|
||||||
|
|
||||||
var progressLayer = CAShapeLayer()
|
var progressLayer = CAShapeLayer()
|
||||||
|
|
||||||
|
static var lineWidth: CGFloat { 4 }
|
||||||
|
|
||||||
|
public override var tintColor: UIColor! {
|
||||||
|
didSet {
|
||||||
|
progressLayer.strokeColor = tintColor.cgColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
|
let lineWidth = Self.lineWidth
|
||||||
// 容器宽度
|
// 容器宽度
|
||||||
let maxSize = CGFloat(28)
|
let size = CGFloat.maximum(frame.height, frame.width)
|
||||||
super.init(frame: .init(x: 0, y: 0, width: maxSize, height: maxSize))
|
super.init(frame: .init(x: 0, y: 0, width: size, height: size))
|
||||||
layer.cornerRadius = maxSize / 2
|
layer.cornerRadius = size / 2
|
||||||
layer.masksToBounds = true
|
layer.masksToBounds = true
|
||||||
// 进度圆半径
|
// 圆环路径
|
||||||
let radius = maxSize / 2 - 4
|
let path = UIBezierPath(arcCenter: CGPoint(x: size / 2, y: size / 2), radius: (size - lineWidth) / 2, startAngle: -CGFloat.pi*0.5, endAngle: CGFloat.pi * 1.5, clockwise: true)
|
||||||
backgroundColor = .white
|
|
||||||
|
|
||||||
let path = UIBezierPath(arcCenter: CGPoint(x: 14, y: 14), radius: radius/2, startAngle: -CGFloat.pi*0.5, endAngle: CGFloat.pi * 1.5, clockwise: true)
|
// 轨道
|
||||||
|
let bgLayer = CAShapeLayer()
|
||||||
|
bgLayer.fillColor = UIColor.clear.cgColor
|
||||||
|
bgLayer.path = path.cgPath
|
||||||
|
bgLayer.strokeColor = UIColor.white.cgColor
|
||||||
|
bgLayer.lineWidth = lineWidth
|
||||||
|
bgLayer.lineCap = .round
|
||||||
|
bgLayer.strokeStart = 0
|
||||||
|
bgLayer.strokeEnd = 1
|
||||||
|
layer.addSublayer(bgLayer)
|
||||||
|
|
||||||
|
// 进度
|
||||||
progressLayer.fillColor = UIColor.clear.cgColor
|
progressLayer.fillColor = UIColor.clear.cgColor
|
||||||
progressLayer.path = path.cgPath
|
progressLayer.path = path.cgPath
|
||||||
|
|
||||||
progressLayer.strokeColor = tintColor.cgColor
|
progressLayer.strokeColor = tintColor.cgColor
|
||||||
progressLayer.lineWidth = radius
|
progressLayer.lineWidth = lineWidth
|
||||||
|
progressLayer.lineCap = .round
|
||||||
progressLayer.strokeStart = 0
|
progressLayer.strokeStart = 0
|
||||||
progressLayer.strokeEnd = 0
|
progressLayer.strokeEnd = 0
|
||||||
layer.addSublayer(progressLayer)
|
layer.addSublayer(progressLayer)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"info" : {
|
"info" : {
|
||||||
"version" : 1,
|
"author" : "xcode",
|
||||||
"author" : "xcode"
|
"version" : 1
|
||||||
}
|
}
|
||||||
}
|
}
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 7.3 KiB |
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"images" : [
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "prohud.questionmark@2x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "prohud.questionmark@3x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "3x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info" : {
|
|
||||||
"author" : "xcode",
|
|
||||||
"version" : 1
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 6.9 KiB |
|
@ -1,22 +0,0 @@
|
||||||
{
|
|
||||||
"images" : [
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "1x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "prohud.rainbow.circle@2x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "2x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename" : "prohud.rainbow.circle@3x.png",
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "3x"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info" : {
|
|
||||||
"author" : "xcode",
|
|
||||||
"version" : 1
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 19 KiB |
|
@ -5,12 +5,12 @@
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "prohud.privacy@2x.png",
|
"filename" : "prohud.rainbow@2x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename" : "prohud.privacy@3x.png",
|
"filename" : "prohud.rainbow@3x.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
}
|
}
|
BIN
Sources/ProHUD/Resources/ProHUD.xcassets/prohud.rainbow.imageset/prohud.rainbow@2x.png
vendored
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
Sources/ProHUD/Resources/ProHUD.xcassets/prohud.rainbow.imageset/prohud.rainbow@3x.png
vendored
Normal file
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 4.7 KiB |
|
@ -31,15 +31,15 @@ public extension Toast {
|
||||||
}
|
}
|
||||||
|
|
||||||
override var titleFontByDefault: UIFont {
|
override var titleFontByDefault: UIFont {
|
||||||
titleFont ?? .systemFont(ofSize: 19, weight: .bold)
|
titleFont ?? .systemFont(ofSize: 18, weight: .bold)
|
||||||
}
|
}
|
||||||
|
|
||||||
override var boldTextFontByDefault: UIFont {
|
override var boldTextFontByDefault: UIFont {
|
||||||
boldTextFont ?? .systemFont(ofSize: 17, weight: .bold)
|
boldTextFont ?? .systemFont(ofSize: 16, weight: .bold)
|
||||||
}
|
}
|
||||||
|
|
||||||
override var bodyFontByDefault: UIFont {
|
override var bodyFontByDefault: UIFont {
|
||||||
bodyFont ?? .systemFont(ofSize: 17, weight: .regular)
|
bodyFont ?? .systemFont(ofSize: 16, weight: .regular)
|
||||||
}
|
}
|
||||||
|
|
||||||
override var animateDurationForBuildInByDefault: CGFloat {
|
override var animateDurationForBuildInByDefault: CGFloat {
|
||||||
|
|
|
@ -77,17 +77,7 @@ extension Toast: DefaultLayout {
|
||||||
self?.pop()
|
self?.pop()
|
||||||
})
|
})
|
||||||
|
|
||||||
// 移除动画
|
setupImageView()
|
||||||
stopRotate(animateLayer)
|
|
||||||
animateLayer = nil
|
|
||||||
animation = nil
|
|
||||||
|
|
||||||
// 移除进度
|
|
||||||
progressView?.removeFromSuperview()
|
|
||||||
// 开始动画
|
|
||||||
if let rotation = vm.rotation {
|
|
||||||
startRotate(rotation)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,4 +116,20 @@ extension Toast {
|
||||||
contentStack.addArrangedSubview(sup)
|
contentStack.addArrangedSubview(sup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupImageView() {
|
||||||
|
// 移除动画
|
||||||
|
stopRotate(animateLayer)
|
||||||
|
animateLayer = nil
|
||||||
|
animation = nil
|
||||||
|
|
||||||
|
// 移除进度
|
||||||
|
progressView?.removeFromSuperview()
|
||||||
|
|
||||||
|
imageView.image = vm.icon
|
||||||
|
if let rotation = vm.rotation {
|
||||||
|
startRotate(rotation)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ extension Toast {
|
||||||
|
|
||||||
/// 更新HUD实例
|
/// 更新HUD实例
|
||||||
/// - Parameter callback: 实例更新代码
|
/// - Parameter callback: 实例更新代码
|
||||||
func update(handler: @escaping (_ toast: Toast) -> Void) {
|
public func update(handler: @escaping (_ toast: Toast) -> Void) {
|
||||||
handler(self)
|
handler(self)
|
||||||
reloadData()
|
reloadData()
|
||||||
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
||||||
|
@ -51,14 +51,12 @@ extension Toast {
|
||||||
/// 查找HUD实例
|
/// 查找HUD实例
|
||||||
/// - Parameter identifier: 唯一标识符
|
/// - Parameter identifier: 唯一标识符
|
||||||
/// - Returns: HUD实例
|
/// - Returns: HUD实例
|
||||||
@discardableResult public static func find(identifier: String, update handler: ((_ toast: Toast) -> Void)? = nil) -> Toast? {
|
@discardableResult public static func find(identifier: String, update handler: ((_ toast: Toast) -> Void)? = nil) -> [Toast] {
|
||||||
guard let vc = ToastWindow.windows.last(where: { $0.toast.identifier == identifier })?.toast else {
|
let arr = ToastWindow.windows.compactMap({ $0.toast }).filter({ $0.identifier == identifier })
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if let handler = handler {
|
if let handler = handler {
|
||||||
vc.update(handler: handler)
|
arr.forEach({ $0.update(handler: handler) })
|
||||||
}
|
}
|
||||||
return vc
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|