-
Notifications
You must be signed in to change notification settings - Fork 1
/
ToastAnimatter.swift
105 lines (93 loc) 路 4.35 KB
/
ToastAnimatter.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
//
// ToastAnimatter.swift
//
//
// Created by BlueSky335 on 2023/3/21.
//
import UIKit
public class ToastAnimatter: ToastAnimatterType {
public enum Position {
case top
case bottom
case center
}
public enum Layout {
case `default`
case replace
case stacke
}
public let position: Position
public let layout: Layout
public var fixedWidth: Bool
public var contentInsets: UIEdgeInsets
public var stackSpace: CGFloat = 10
public init(position: Position = .bottom, layout: Layout = .default, fixedWidth: Bool = false, contentInsets: UIEdgeInsets? = nil) {
self.position = position
self.layout = layout
self.fixedWidth = fixedWidth
self.contentInsets = contentInsets ?? .init(top: 16, left: 16, bottom: 16, right: 16)
}
private weak var preToastView: UIView?
public func show(toastView: UIView, in center: ToastCenter, finish: @escaping () -> Void) {
toastView.translatesAutoresizingMaskIntoConstraints = false
let window = center.window
window.addSubview(toastView)
if fixedWidth {
toastView.leftAnchor.constraint(equalTo: window.safeAreaLayoutGuide.leftAnchor, constant: contentInsets.left).isActive = true
toastView.rightAnchor.constraint(equalTo: window.safeAreaLayoutGuide.rightAnchor, constant: -contentInsets.right).isActive = true
} else {
toastView.leftAnchor.constraint(greaterThanOrEqualTo: window.safeAreaLayoutGuide.leftAnchor, constant: contentInsets.left).isActive = true
toastView.rightAnchor.constraint(lessThanOrEqualTo: window.safeAreaLayoutGuide.rightAnchor, constant: -contentInsets.right).isActive = true
}
toastView.centerXAnchor.constraint(equalTo: window.centerXAnchor).isActive = true
toastView.alpha = 0
if position == .bottom {
toastView.bottomAnchor.constraint(lessThanOrEqualTo: window.safeAreaLayoutGuide.bottomAnchor).isActive = true
toastView.bottomAnchor.constraint(lessThanOrEqualTo: window.bottomAnchor, constant: -contentInsets.bottom).isActive = true
toastView.bottomAnchor.constraint(lessThanOrEqualTo: center.keyboardLayoutGuide.topAnchor, constant: -contentInsets.bottom).isActive = true
} else if position == .top {
toastView.topAnchor.constraint(greaterThanOrEqualTo: window.safeAreaLayoutGuide.topAnchor, constant: contentInsets.top).isActive = true
} else if position == .center {
let center = toastView.centerYAnchor.constraint(lessThanOrEqualTo: window.safeAreaLayoutGuide.centerYAnchor)
center.isActive = true
center.priority = .defaultHigh
}
if layout == .stacke {
if position == .bottom || position == .center {
toastView.transform = .init(translationX: 0, y: 10)
} else if position == .top {
toastView.transform = .init(translationX: 0, y: -10)
}
}
window.layoutIfNeeded()
if layout == .replace {
center.cancellAllToast()
} else if layout == .stacke {
if let preToastView = preToastView, preToastView.superview == window {
if position == .bottom || position == .center {
toastView.transform = .init(translationX: 0, y: 10)
preToastView.bottomAnchor.constraint(lessThanOrEqualTo: toastView.topAnchor, constant: -stackSpace).isActive = true
} else if position == .top {
toastView.transform = .init(translationX: 0, y: -10)
preToastView.topAnchor.constraint(greaterThanOrEqualTo: toastView.bottomAnchor, constant: stackSpace).isActive = true
}
}
}
preToastView = toastView
UIView.animate(withDuration: 0.3, delay: 0, options: [.curveEaseOut]) {
toastView.alpha = 1
toastView.transform = .identity
window.layoutIfNeeded()
} completion: { _ in
finish()
}
}
public func hide(toastView: UIView, in center: ToastCenter, finish: @escaping () -> Void) {
UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseIn]) {
toastView.alpha = 0
center.window.layoutIfNeeded()
} completion: { _ in
finish()
}
}
}