mirror of https://github.com/xaoxuu/ProHUD
UI优化
This commit is contained in:
parent
abe4738c0f
commit
7e672707cf
|
@ -69,20 +69,46 @@ class AlertVC: ListVC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list.add(title: "文字 + 按钮") { section in
|
list.add(title: "文字 + 按钮") { section in
|
||||||
|
section.add(title: "只有一小段文字 + 无背景色按钮") {
|
||||||
|
Alert { alert in
|
||||||
|
alert.config.boldTextFont = .systemFont(ofSize: 15)
|
||||||
|
alert.config.buttonFont = .systemFont(ofSize: 15)
|
||||||
|
alert.config.cardCornerRadius = 12
|
||||||
|
alert.vm.title = "你正在使用移动网络观看"
|
||||||
|
} .onViewDidLoad { vc in
|
||||||
|
guard let alert = vc as? Alert else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
alert.add(contentSpacing: 30)
|
||||||
|
let v = UIView()
|
||||||
|
v.backgroundColor = UIColor("#f2f2f2")
|
||||||
|
alert.add(subview: v).snp.makeConstraints { make in
|
||||||
|
make.left.right.equalToSuperview()
|
||||||
|
make.height.equalTo(1)
|
||||||
|
}
|
||||||
|
alert.add(contentSpacing: 16)
|
||||||
|
alert.add(action: "确定", style: .plain(textColor: UIColor("#14cccc")))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
section.add(title: "只有一段文字 + 无背景色按钮") {
|
section.add(title: "只有一段文字 + 无背景色按钮") {
|
||||||
Alert { alert in
|
Alert { alert in
|
||||||
alert.config.boldTextFont = .systemFont(ofSize: 15)
|
alert.config.boldTextFont = .systemFont(ofSize: 15)
|
||||||
alert.config.buttonFont = .systemFont(ofSize: 15)
|
alert.config.buttonFont = .systemFont(ofSize: 15)
|
||||||
alert.config.cardCornerRadius = 12
|
alert.config.cardCornerRadius = 12
|
||||||
|
|
||||||
alert.vm.title = "为了维护社区氛围,上麦用户需进行主播认证"
|
alert.vm.title = "为了维护社区氛围,上麦用户需进行主播认证"
|
||||||
|
} .onViewDidLoad { vc in
|
||||||
|
guard let alert = vc as? Alert else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
alert.add(contentSpacing: 30)
|
||||||
let v = UIView()
|
let v = UIView()
|
||||||
v.backgroundColor = UIColor("#F7F7F7")
|
v.backgroundColor = UIColor("#f2f2f2")
|
||||||
alert.add(subview: v).snp.makeConstraints { make in
|
alert.add(subview: v).snp.makeConstraints { make in
|
||||||
make.left.right.equalToSuperview()
|
make.left.right.equalToSuperview()
|
||||||
make.height.equalTo(1)
|
make.height.equalTo(1)
|
||||||
}
|
}
|
||||||
alert.add(spacing: 16)
|
alert.add(contentSpacing: 16)
|
||||||
alert.add(action: "取消", style: .plain(textColor: UIColor("#939999")))
|
alert.add(action: "取消", style: .plain(textColor: UIColor("#939999")))
|
||||||
alert.add(action: "确定", style: .plain(textColor: UIColor("#14cccc")))
|
alert.add(action: "确定", style: .plain(textColor: UIColor("#14cccc")))
|
||||||
}
|
}
|
||||||
|
@ -281,7 +307,7 @@ class AlertVC: ListVC {
|
||||||
slider.maximumValue = 100
|
slider.maximumValue = 100
|
||||||
slider.value = 50
|
slider.value = 50
|
||||||
alert.add(action: slider)
|
alert.add(action: slider)
|
||||||
alert.add(spacing: 24, for: alert.actionStack)
|
alert.add(actionSpacing: 124)
|
||||||
alert.add(action: "取消", style: .gray)
|
alert.add(action: "取消", style: .gray)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -305,7 +331,7 @@ class AlertVC: ListVC {
|
||||||
// Fallback on earlier versions
|
// Fallback on earlier versions
|
||||||
}
|
}
|
||||||
alert.config.actionAxis = .vertical
|
alert.config.actionAxis = .vertical
|
||||||
alert.add(spacing: 24, for: alert.actionStack)
|
alert.add(contentSpacing: 24)
|
||||||
alert.add(action: "OK", style: .gray)
|
alert.add(action: "OK", style: .gray)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ public class Alert: ProHUD.Controller {
|
||||||
let lb = UILabel()
|
let lb = UILabel()
|
||||||
lb.textColor = config.primaryLabelColor
|
lb.textColor = config.primaryLabelColor
|
||||||
lb.font = config.titleFontByDefault
|
lb.font = config.titleFontByDefault
|
||||||
lb.textAlignment = .justified
|
lb.textAlignment = .left
|
||||||
lb.numberOfLines = config.titleMaxLines
|
lb.numberOfLines = config.titleMaxLines
|
||||||
return lb
|
return lb
|
||||||
}()
|
}()
|
||||||
|
@ -56,7 +56,7 @@ public class Alert: ProHUD.Controller {
|
||||||
let lb = UILabel()
|
let lb = UILabel()
|
||||||
lb.textColor = config.primaryLabelColor
|
lb.textColor = config.primaryLabelColor
|
||||||
lb.font = config.bodyFontByDefault
|
lb.font = config.bodyFontByDefault
|
||||||
lb.textAlignment = .justified
|
lb.textAlignment = .left
|
||||||
lb.numberOfLines = config.bodyMaxLines
|
lb.numberOfLines = config.bodyMaxLines
|
||||||
return lb
|
return lb
|
||||||
}()
|
}()
|
||||||
|
@ -100,7 +100,8 @@ public class Alert: ProHUD.Controller {
|
||||||
public override func viewDidLoad() {
|
public override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
view.tintColor = config.tintColor
|
view.tintColor = config.tintColor
|
||||||
reloadData()
|
reloadData(animated: false)
|
||||||
|
navEvents[.onViewDidLoad]?(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
//
|
||||||
|
// AlertButton.swift
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Created by xaoxuu on 2023/4/27.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
public class AlertButton: Button {
|
||||||
|
override var customEdgeInset: UIEdgeInsets {
|
||||||
|
.init(top: 12, left: 24, bottom: 12, right: 24)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ extension Alert: InternalConvenienceLayout {
|
||||||
insert(action: action, at: actionStack.arrangedSubviews.count)
|
insert(action: action, at: actionStack.arrangedSubviews.count)
|
||||||
}
|
}
|
||||||
@discardableResult public func insert(action: Action, at index: Int) -> Button {
|
@discardableResult public func insert(action: Action, at index: Int) -> Button {
|
||||||
let btn = Button(config: config, action: action)
|
let btn = AlertButton(config: config, action: action)
|
||||||
if index < actionStack.arrangedSubviews.count {
|
if index < actionStack.arrangedSubviews.count {
|
||||||
actionStack.insertArrangedSubview(btn, at: index)
|
actionStack.insertArrangedSubview(btn, at: index)
|
||||||
} else {
|
} else {
|
||||||
|
@ -32,7 +32,7 @@ extension Alert: InternalConvenienceLayout {
|
||||||
self?.pop()
|
self?.pop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isViewLoaded {
|
if isViewDisplayed {
|
||||||
self.actionStack.layoutIfNeeded()
|
self.actionStack.layoutIfNeeded()
|
||||||
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
|
@ -78,7 +78,7 @@ extension Alert: InternalConvenienceLayout {
|
||||||
buttonEvents[view] = nil
|
buttonEvents[view] = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isViewLoaded {
|
if isViewDisplayed {
|
||||||
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
||||||
self.actionStack.layoutIfNeeded()
|
self.actionStack.layoutIfNeeded()
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
|
@ -105,18 +105,33 @@ extension Alert: InternalConvenienceLayout {
|
||||||
|
|
||||||
// MARK: 布局工具
|
// MARK: 布局工具
|
||||||
|
|
||||||
public func add(spacing: CGFloat) {
|
public func set(spacing: CGFloat, after: UIView?, in stack: UIStackView) {
|
||||||
add(spacing: spacing, for: contentStack)
|
|
||||||
}
|
|
||||||
|
|
||||||
public func add(spacing: CGFloat, for stack: UIStackView) {
|
|
||||||
if #available(iOS 11.0, *) {
|
if #available(iOS 11.0, *) {
|
||||||
if let last = stack.arrangedSubviews.last {
|
if let after = after ?? stack.arrangedSubviews.last {
|
||||||
stack.setCustomSpacing(spacing, after: last)
|
stack.setCustomSpacing(spacing, after: after)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func set(contentSpacing: CGFloat, after: UIView?) {
|
||||||
|
set(spacing: contentSpacing, after: after, in: contentStack)
|
||||||
|
}
|
||||||
|
public func set(textSpacing: CGFloat, after: UIView?) {
|
||||||
|
set(spacing: textSpacing, after: after, in: textStack)
|
||||||
|
}
|
||||||
|
public func set(actionSpacing: CGFloat, after: UIView?) {
|
||||||
|
set(spacing: actionSpacing, after: after, in: actionStack)
|
||||||
|
}
|
||||||
|
public func add(contentSpacing: CGFloat) {
|
||||||
|
set(spacing: contentSpacing, after: nil, in: contentStack)
|
||||||
|
}
|
||||||
|
public func add(textSpacing: CGFloat) {
|
||||||
|
set(spacing: textSpacing, after: nil, in: textStack)
|
||||||
|
}
|
||||||
|
public func add(actionSpacing: CGFloat) {
|
||||||
|
set(spacing: actionSpacing, after: nil, in: actionStack)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: 完全自定义布局
|
// MARK: 完全自定义布局
|
||||||
|
|
||||||
@discardableResult public func set(customView: UIView) -> UIView {
|
@discardableResult public func set(customView: UIView) -> UIView {
|
||||||
|
|
|
@ -13,10 +13,13 @@ extension Alert: DefaultLayout {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
func reloadDataByDefault() {
|
func reloadData(animated: Bool) {
|
||||||
|
if self.cfg.customReloadData?(self) == true {
|
||||||
|
return
|
||||||
|
}
|
||||||
let isFirstLayout: Bool
|
let isFirstLayout: Bool
|
||||||
if contentView.superview == nil {
|
if contentView.superview == nil {
|
||||||
isFirstLayout = true
|
isFirstLayout = animated
|
||||||
// 布局主容器视图
|
// 布局主容器视图
|
||||||
loadContentViewIfNeeded()
|
loadContentViewIfNeeded()
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,19 +45,22 @@ extension Alert: DefaultLayout {
|
||||||
contentView.layoutIfNeeded()
|
contentView.layoutIfNeeded()
|
||||||
|
|
||||||
// 动画
|
// 动画
|
||||||
if isFirstLayout {
|
if animated {
|
||||||
view.layoutIfNeeded()
|
if isFirstLayout {
|
||||||
imageView.transform = .init(scaleX: 0.7, y: 0.7)
|
view.layoutIfNeeded()
|
||||||
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
imageView.transform = .init(scaleX: 0.7, y: 0.7)
|
||||||
self.view.layoutIfNeeded()
|
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
||||||
self.imageView.transform = .identity
|
self.view.layoutIfNeeded()
|
||||||
|
self.imageView.transform = .identity
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
||||||
|
self.view.layoutIfNeeded()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
view.layoutIfNeeded()
|
||||||
self.view.layoutIfNeeded()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadContentViewIfNeeded() {
|
func loadContentViewIfNeeded() {
|
||||||
|
@ -166,14 +172,14 @@ extension Alert {
|
||||||
contentStack.insertArrangedSubview(textStack, at: 0)
|
contentStack.insertArrangedSubview(textStack, at: 0)
|
||||||
}
|
}
|
||||||
textStack.snp.remakeConstraints { (mk) in
|
textStack.snp.remakeConstraints { (mk) in
|
||||||
mk.top.greaterThanOrEqualTo(contentView).inset(config.padding*1.75)
|
mk.top.greaterThanOrEqualTo(contentView).inset(config.padding*1.875)
|
||||||
mk.bottom.lessThanOrEqualTo(contentView).inset(config.padding*1.75)
|
mk.bottom.lessThanOrEqualTo(contentView).inset(config.padding*1.875)
|
||||||
if UIScreen.main.bounds.width < 414 {
|
if UIScreen.main.bounds.width < 414 {
|
||||||
mk.left.greaterThanOrEqualTo(contentView).inset(config.padding*1.5)
|
|
||||||
mk.right.lessThanOrEqualTo(contentView).inset(config.padding*1.5)
|
|
||||||
} else {
|
|
||||||
mk.left.greaterThanOrEqualTo(contentView).inset(config.padding*2)
|
mk.left.greaterThanOrEqualTo(contentView).inset(config.padding*2)
|
||||||
mk.right.lessThanOrEqualTo(contentView).inset(config.padding*2)
|
mk.right.lessThanOrEqualTo(contentView).inset(config.padding*2)
|
||||||
|
} else {
|
||||||
|
mk.left.greaterThanOrEqualTo(contentView).inset(config.padding*3)
|
||||||
|
mk.right.lessThanOrEqualTo(contentView).inset(config.padding*3)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,11 @@ open class Controller: UIViewController {
|
||||||
|
|
||||||
var navEvents = [NavEvent: ((Controller) -> Void)]()
|
var navEvents = [NavEvent: ((Controller) -> Void)]()
|
||||||
|
|
||||||
|
@discardableResult public func onViewDidLoad(_ callback: ((_ vc: Controller) -> Void)?) -> Controller {
|
||||||
|
navEvents[.onViewDidLoad] = callback
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
@discardableResult public func onViewWillAppear(_ callback: ((_ vc: Controller) -> Void)?) -> Controller {
|
@discardableResult public func onViewWillAppear(_ callback: ((_ vc: Controller) -> Void)?) -> Controller {
|
||||||
navEvents[.onViewWillAppear] = callback
|
navEvents[.onViewWillAppear] = callback
|
||||||
return self
|
return self
|
||||||
|
|
|
@ -17,10 +17,7 @@ public extension CommonLayout {
|
||||||
guard let self = self as? DefaultLayout else {
|
guard let self = self as? DefaultLayout else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if self.cfg.customReloadData?(self) == true {
|
self.reloadData(animated: true)
|
||||||
return
|
|
||||||
}
|
|
||||||
self.reloadDataByDefault()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,9 +54,12 @@ public protocol ConvenienceLayout {
|
||||||
|
|
||||||
// MARK: 布局工具
|
// MARK: 布局工具
|
||||||
|
|
||||||
/// 增加空隙(仅iOS11以上可用)
|
/// 设置stack容器内的元素间距
|
||||||
/// - Parameter spacing: 自定义空隙
|
/// - Parameters:
|
||||||
func add(spacing: CGFloat)
|
/// - spacing: 间距
|
||||||
|
/// - after: 哪个view后面
|
||||||
|
/// - stack: 在哪个stack容器内
|
||||||
|
func set(spacing: CGFloat, after: UIView?, in stack: UIStackView)
|
||||||
|
|
||||||
// MARK: 自定义布局
|
// MARK: 自定义布局
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,7 @@ protocol DefaultLayout: CommonLayout {
|
||||||
|
|
||||||
var cfg: Configuration { get }
|
var cfg: Configuration { get }
|
||||||
|
|
||||||
func reloadDataByDefault()
|
func reloadData(animated: Bool)
|
||||||
|
|
||||||
func loadContentViewIfNeeded()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ 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 isViewDisplayed else { return }
|
||||||
guard let superview = imageView.superview else { return }
|
guard let superview = imageView.superview else { return }
|
||||||
if progressView == nil {
|
if progressView == nil {
|
||||||
let width = imageView.frame.size.width + ProgressView.lineWidth * 2
|
let width = imageView.frame.size.width + ProgressView.lineWidth * 2
|
||||||
|
|
|
@ -13,12 +13,13 @@ open class Button: UIButton {
|
||||||
|
|
||||||
public internal(set) var action: Action?
|
public internal(set) var action: Action?
|
||||||
|
|
||||||
var edgeInset: CGFloat { 8 * 1.5 }
|
var customEdgeInset: UIEdgeInsets {
|
||||||
|
.init(top: 12, left: 24, bottom: 12, right: 24)
|
||||||
|
}
|
||||||
|
|
||||||
public override init(frame: CGRect) {
|
public override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
let padding = edgeInset
|
contentEdgeInsets = customEdgeInset
|
||||||
contentEdgeInsets = .init(top: padding, left: padding * 2, bottom: padding, right: padding * 2)
|
|
||||||
addTarget(self, action: #selector(self._onTouchUp(_:)), for: [.touchUpInside, .touchUpOutside])
|
addTarget(self, action: #selector(self._onTouchUp(_:)), for: [.touchUpInside, .touchUpOutside])
|
||||||
addTarget(self, action: #selector(self._onTouchDown(_:)), for: .touchDown)
|
addTarget(self, action: #selector(self._onTouchDown(_:)), for: .touchDown)
|
||||||
addTarget(self, action: #selector(self._onTouchUpInside(_:)), for: .touchUpInside)
|
addTarget(self, action: #selector(self._onTouchUpInside(_:)), for: .touchUpInside)
|
||||||
|
|
|
@ -64,10 +64,12 @@ public class Sheet: Controller {
|
||||||
let tap = UITapGestureRecognizer(target: self, action: #selector(_onTappedBackground(_:)))
|
let tap = UITapGestureRecognizer(target: self, action: #selector(_onTappedBackground(_:)))
|
||||||
backgroundView.addGestureRecognizer(tap)
|
backgroundView.addGestureRecognizer(tap)
|
||||||
|
|
||||||
reloadData()
|
reloadData(animated: false)
|
||||||
|
|
||||||
_translateOut()
|
_translateOut()
|
||||||
|
|
||||||
|
navEvents[.onViewDidLoad]?(self)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,5 +8,7 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
public class SheetButton: Button {
|
public class SheetButton: Button {
|
||||||
override var edgeInset: CGFloat { 8 * 1.75 }
|
override var customEdgeInset: UIEdgeInsets {
|
||||||
|
.init(top: 14, left: 28, bottom: 14, right: 28)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ extension Sheet: ConvenienceLayout {
|
||||||
self?.pop()
|
self?.pop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isViewLoaded {
|
if isViewDisplayed {
|
||||||
self.contentStack.layoutIfNeeded()
|
self.contentStack.layoutIfNeeded()
|
||||||
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
|
@ -74,7 +74,7 @@ extension Sheet: ConvenienceLayout {
|
||||||
buttonEvents[view] = nil
|
buttonEvents[view] = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isViewLoaded {
|
if isViewDisplayed {
|
||||||
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
||||||
self.contentStack.layoutIfNeeded()
|
self.contentStack.layoutIfNeeded()
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
|
@ -92,14 +92,18 @@ extension Sheet: ConvenienceLayout {
|
||||||
|
|
||||||
// MARK: 布局工具
|
// MARK: 布局工具
|
||||||
|
|
||||||
public func add(spacing: CGFloat) {
|
public func set(spacing: CGFloat, after: UIView?, in stack: UIStackView) {
|
||||||
if #available(iOS 11.0, *) {
|
if #available(iOS 11.0, *) {
|
||||||
if let last = contentStack.arrangedSubviews.last {
|
if let after = after ?? stack.arrangedSubviews.last {
|
||||||
contentStack.setCustomSpacing(spacing, after: last)
|
stack.setCustomSpacing(spacing, after: after)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func add(spacing: CGFloat) {
|
||||||
|
set(spacing: spacing, after: nil, in: contentStack)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: 完全自定义布局
|
// MARK: 完全自定义布局
|
||||||
|
|
||||||
@discardableResult public func set(customView: UIView) -> UIView {
|
@discardableResult public func set(customView: UIView) -> UIView {
|
||||||
|
|
|
@ -13,7 +13,10 @@ extension Sheet: DefaultLayout {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
func reloadDataByDefault() {
|
func reloadData(animated: Bool) {
|
||||||
|
if self.cfg.customReloadData?(self) == true {
|
||||||
|
return
|
||||||
|
}
|
||||||
// background
|
// background
|
||||||
if backgroundView.superview == nil {
|
if backgroundView.superview == nil {
|
||||||
view.insertSubview(backgroundView, at: 0)
|
view.insertSubview(backgroundView, at: 0)
|
||||||
|
@ -30,10 +33,9 @@ extension Sheet: DefaultLayout {
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadContentViewIfNeeded() {
|
private func loadContentViewIfNeeded() {
|
||||||
contentView.layer.cornerRadiusWithContinuous = config.cardCornerRadiusByDefault
|
contentView.layer.cornerRadiusWithContinuous = config.cardCornerRadiusByDefault
|
||||||
if contentView.superview != view {
|
if contentView.superview != view {
|
||||||
view.insertSubview(contentView, aboveSubview: backgroundView)
|
view.insertSubview(contentView, aboveSubview: backgroundView)
|
||||||
|
@ -92,5 +94,4 @@ extension Sheet: DefaultLayout {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,9 @@ public class Toast: Controller {
|
||||||
let pan = UIPanGestureRecognizer(target: self, action: #selector(_onPanGesture(_:)))
|
let pan = UIPanGestureRecognizer(target: self, action: #selector(_onPanGesture(_:)))
|
||||||
view.addGestureRecognizer(pan)
|
view.addGestureRecognizer(pan)
|
||||||
|
|
||||||
reloadData()
|
reloadData(animated: false)
|
||||||
|
navEvents[.onViewDidLoad]?(self)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func onTapped(action: @escaping (_ toast: Toast) -> Void) {
|
public func onTapped(action: @escaping (_ toast: Toast) -> Void) {
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
public class ToastButton: Button {
|
public class ToastButton: Button {
|
||||||
override var edgeInset: CGFloat { 8 * 1.25 }
|
override var customEdgeInset: UIEdgeInsets {
|
||||||
|
.init(top: 10, left: 24, bottom: 10, right: 24)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,21 +7,35 @@
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
public extension Toast {
|
extension Toast: ConvenienceLayout {
|
||||||
|
|
||||||
@discardableResult func add(subview: UIView) -> UIView {
|
// MARK: 增加
|
||||||
if contentStack.superview != nil {
|
|
||||||
contentStack.removeFromSuperview()
|
/// 增加一个按钮
|
||||||
|
/// - Parameters:
|
||||||
|
/// - title: 标题
|
||||||
|
/// - style: 样式
|
||||||
|
/// - identifier: 唯一标识符
|
||||||
|
/// - handler: 点击事件
|
||||||
|
/// - Returns: 按钮实例
|
||||||
|
@discardableResult public func add(action title: String, style: Action.Style = .tinted, identifier: String? = nil, handler: ((_ toast: Toast) -> Void)? = nil) -> Button {
|
||||||
|
if let handler = handler {
|
||||||
|
let action = Action(identifier: identifier, style: style, title: title) { vc in
|
||||||
|
if let vc = vc as? Toast {
|
||||||
|
handler(vc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return add(action: action)
|
||||||
|
} else {
|
||||||
|
return add(action: .init(identifier: identifier, style: style, title: title, handler: nil))
|
||||||
}
|
}
|
||||||
contentView.addSubview(subview)
|
|
||||||
return subview
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult func add(action: Action) -> Button {
|
@discardableResult public func add(action: Action) -> Button {
|
||||||
insert(action: action, at: actionStack.arrangedSubviews.count)
|
insert(action: action, at: actionStack.arrangedSubviews.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult func insert(action: Action, at index: Int) -> Button {
|
@discardableResult public func insert(action: Action, at index: Int) -> Button {
|
||||||
let btn = ToastButton(config: config, action: action)
|
let btn = ToastButton(config: config, action: action)
|
||||||
if index < actionStack.arrangedSubviews.count {
|
if index < actionStack.arrangedSubviews.count {
|
||||||
actionStack.insertArrangedSubview(btn, at: index)
|
actionStack.insertArrangedSubview(btn, at: index)
|
||||||
|
@ -37,7 +51,7 @@ public extension Toast {
|
||||||
self?.pop()
|
self?.pop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isViewLoaded {
|
if isViewDisplayed {
|
||||||
self.actionStack.layoutIfNeeded()
|
self.actionStack.layoutIfNeeded()
|
||||||
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
|
@ -46,36 +60,111 @@ public extension Toast {
|
||||||
return btn
|
return btn
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: 布局工具
|
|
||||||
|
|
||||||
func add(spacing: CGFloat) {
|
// MARK: 查找
|
||||||
if #available(iOS 11.0, *) {
|
public func button(for identifier: String) -> Button? {
|
||||||
if let last = contentStack.arrangedSubviews.last {
|
if let index = actionIndex(for: identifier) {
|
||||||
contentStack.setCustomSpacing(spacing, after: last)
|
return contentStack.arrangedSubviews[index] as? Button
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: 更新
|
||||||
|
public func update(action title: String, style: Action.Style? = nil, for identifier: String) {
|
||||||
|
if let btn = button(for: identifier), let act = btn.action {
|
||||||
|
act.title = title
|
||||||
|
if let style = style {
|
||||||
|
act.style = style
|
||||||
}
|
}
|
||||||
|
btn.update(config: config, action: act)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 增加一个按钮
|
// MARK: 删除
|
||||||
/// - Parameters:
|
|
||||||
/// - title: 标题
|
public func remove(actions finder: Action.Filter) {
|
||||||
/// - style: 样式
|
if finder.ids.count > 0 {
|
||||||
/// - identifier: 唯一标识符
|
for identifier in finder.ids {
|
||||||
/// - handler: 点击事件
|
while let index = actionIndex(for: identifier), index < contentStack.arrangedSubviews.count {
|
||||||
/// - Returns: 按钮实例
|
let view = contentStack.arrangedSubviews[index]
|
||||||
@discardableResult func add(action title: String, style: Action.Style = .tinted, identifier: String? = nil, handler: ((_ toast: Toast) -> Void)? = nil) -> Button {
|
contentStack.removeArrangedSubview(view)
|
||||||
if let handler = handler {
|
view.removeFromSuperview()
|
||||||
let action = Action(identifier: identifier, style: style, title: title) { vc in
|
buttonEvents[view] = nil
|
||||||
if let vc = vc as? Toast {
|
|
||||||
handler(vc)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return add(action: action)
|
|
||||||
} else {
|
} else {
|
||||||
return add(action: .init(identifier: identifier, style: style, title: title, handler: nil))
|
for view in contentStack.arrangedSubviews {
|
||||||
|
contentStack.removeArrangedSubview(view)
|
||||||
|
view.removeFromSuperview()
|
||||||
|
buttonEvents[view] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isViewDisplayed {
|
||||||
|
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
||||||
|
self.contentStack.layoutIfNeeded()
|
||||||
|
self.view.layoutIfNeeded()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: 自定义控件
|
||||||
|
|
||||||
|
@discardableResult public func add(subview: UIView) -> UIView {
|
||||||
|
if contentStack.superview != nil {
|
||||||
|
contentStack.removeFromSuperview()
|
||||||
|
}
|
||||||
|
contentView.addSubview(subview)
|
||||||
|
return subview
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: 布局工具
|
||||||
|
|
||||||
|
public func set(spacing: CGFloat, after: UIView?, in stack: UIStackView) {
|
||||||
|
if #available(iOS 11.0, *) {
|
||||||
|
if let after = after ?? stack.arrangedSubviews.last {
|
||||||
|
stack.setCustomSpacing(spacing, after: after)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func set(contentSpacing: CGFloat, after: UIView?) {
|
||||||
|
set(spacing: contentSpacing, after: after, in: contentStack)
|
||||||
|
}
|
||||||
|
public func set(textSpacing: CGFloat, after: UIView?) {
|
||||||
|
set(spacing: textSpacing, after: after, in: textStack)
|
||||||
|
}
|
||||||
|
public func set(actionSpacing: CGFloat, after: UIView?) {
|
||||||
|
set(spacing: actionSpacing, after: after, in: actionStack)
|
||||||
|
}
|
||||||
|
public func add(contentSpacing: CGFloat) {
|
||||||
|
set(spacing: contentSpacing, after: nil, in: contentStack)
|
||||||
|
}
|
||||||
|
public func add(textSpacing: CGFloat) {
|
||||||
|
set(spacing: textSpacing, after: nil, in: textStack)
|
||||||
|
}
|
||||||
|
public func add(actionSpacing: CGFloat) {
|
||||||
|
set(spacing: actionSpacing, after: nil, in: actionStack)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: 完全自定义布局
|
||||||
|
|
||||||
|
public func set(customView: UIView) -> UIView {
|
||||||
|
self.customView = customView
|
||||||
|
contentView.addSubview(customView)
|
||||||
|
return customView
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: internal
|
||||||
|
func actionIndex(for identifier: String) -> Int? {
|
||||||
|
let arr = contentStack.arrangedSubviews.compactMap({ $0 as? Button })
|
||||||
|
for i in 0 ..< arr.count {
|
||||||
|
if arr[i].action?.identifier == identifier {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,10 @@ extension Toast: DefaultLayout {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
func reloadDataByDefault() {
|
func reloadData(animated: Bool) {
|
||||||
|
if self.cfg.customReloadData?(self) == true {
|
||||||
|
return
|
||||||
|
}
|
||||||
loadContentViewIfNeeded()
|
loadContentViewIfNeeded()
|
||||||
loadContentMaskViewIfNeeded()
|
loadContentMaskViewIfNeeded()
|
||||||
guard customView == nil else {
|
guard customView == nil else {
|
||||||
|
|
Loading…
Reference in New Issue