mirror of https://github.com/xaoxuu/ProHUD
更新实例后自动更新window布局
This commit is contained in:
parent
c3afd50eac
commit
c57b859555
|
@ -189,8 +189,8 @@ class DemoCapsuleVC: ListVC {
|
||||||
section.add(title: "指定id=a, haha") {
|
section.add(title: "指定id=a, haha") {
|
||||||
Capsule(.identifier("a").message("id=a, haha"))
|
Capsule(.identifier("a").message("id=a, haha"))
|
||||||
}
|
}
|
||||||
section.add(title: "指定id=a, hahaha") {
|
section.add(title: "指定id=a, hahahahahaha") {
|
||||||
Capsule(.identifier("a").message("id=a, hahaha"))
|
Capsule(.identifier("a").message("id=a, hahahahahaha"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -233,7 +233,7 @@ class DemoToastVC: ListVC {
|
||||||
}
|
}
|
||||||
section.add(title: "不存在就创建,存在就更新") {
|
section.add(title: "不存在就创建,存在就更新") {
|
||||||
i += 1
|
i += 1
|
||||||
Toast(.identifier("loading").title("正在加载\(i)").message("这条消息不会重复显示多条"))
|
Toast(.identifier("loading").title("正在加载\(i)").message("这条消息\n不会重复显示多条"))
|
||||||
}
|
}
|
||||||
section.add(title: "如果存在就更新,如果不存在就忽略") {
|
section.add(title: "如果存在就更新,如果不存在就忽略") {
|
||||||
i += 1
|
i += 1
|
||||||
|
|
|
@ -25,7 +25,9 @@ extension CapsuleTarget: DefaultLayout {
|
||||||
loadContentMaskViewIfNeeded()
|
loadContentMaskViewIfNeeded()
|
||||||
|
|
||||||
// text
|
// text
|
||||||
|
if contentStack.arrangedSubviews.contains(textLabel) == false {
|
||||||
contentStack.addArrangedSubview(textLabel)
|
contentStack.addArrangedSubview(textLabel)
|
||||||
|
}
|
||||||
var text = [vm?.title ?? "", vm?.message ?? ""].filter({ $0.count > 0 }).joined(separator: " ")
|
var text = [vm?.title ?? "", vm?.message ?? ""].filter({ $0.count > 0 }).joined(separator: " ")
|
||||||
if text.count > 0 {
|
if text.count > 0 {
|
||||||
textLabel.snp.remakeConstraints { make in
|
textLabel.snp.remakeConstraints { make in
|
||||||
|
@ -47,6 +49,7 @@ extension CapsuleTarget: DefaultLayout {
|
||||||
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
UIView.animateEaseOut(duration: config.animateDurationForReloadByDefault) {
|
||||||
self.view.layoutIfNeeded()
|
self.view.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
|
updateWindowSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -88,7 +91,9 @@ extension CapsuleTarget: DefaultLayout {
|
||||||
if vm?.icon == nil && vm?.iconURL == nil {
|
if vm?.icon == nil && vm?.iconURL == nil {
|
||||||
contentStack.removeArrangedSubview(imageView)
|
contentStack.removeArrangedSubview(imageView)
|
||||||
} else {
|
} else {
|
||||||
|
if contentStack.arrangedSubviews.contains(imageView) == false {
|
||||||
contentStack.insertArrangedSubview(imageView, at: 0)
|
contentStack.insertArrangedSubview(imageView, at: 0)
|
||||||
|
}
|
||||||
if config.iconSizeByDefault != .zero {
|
if config.iconSizeByDefault != .zero {
|
||||||
imageView.snp.remakeConstraints { make in
|
imageView.snp.remakeConstraints { make in
|
||||||
make.height.equalTo(config.iconSizeByDefault)
|
make.height.equalTo(config.iconSizeByDefault)
|
||||||
|
@ -106,4 +111,47 @@ extension CapsuleTarget: DefaultLayout {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getWindowSize(window: CapsuleWindow) -> CGSize {
|
||||||
|
let cardEdgeInsetsByDefault = config.cardEdgeInsetsByDefault
|
||||||
|
view.layoutIfNeeded()
|
||||||
|
var size = contentStack.frame.size
|
||||||
|
let width = min(config.cardMaxWidthByDefault, size.width + cardEdgeInsetsByDefault.left + cardEdgeInsetsByDefault.right)
|
||||||
|
let height = min(config.cardMaxHeightByDefault, size.height + cardEdgeInsetsByDefault.top + cardEdgeInsetsByDefault.bottom)
|
||||||
|
return .init(width: width, height: max(height, config.cardMinHeight))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getWindowFrame(size: CGSize) -> CGRect {
|
||||||
|
// 应用到frame
|
||||||
|
let newFrame: CGRect
|
||||||
|
switch vm?.position {
|
||||||
|
case .top, .none:
|
||||||
|
let topLayoutMargins = AppContext.appWindow?.safeAreaInsets.top ?? 8
|
||||||
|
let y = max(topLayoutMargins, 8)
|
||||||
|
newFrame = .init(x: (AppContext.appBounds.width - size.width) / 2, y: y, width: size.width, height: size.height)
|
||||||
|
case .middle:
|
||||||
|
newFrame = .init(x: (AppContext.appBounds.width - size.width) / 2, y: (AppContext.appBounds.height - size.height) / 2 - 20, width: size.width, height: size.height)
|
||||||
|
case .bottom:
|
||||||
|
let bottomLayoutMargins = AppContext.appWindow?.layoutMargins.bottom ?? 8
|
||||||
|
let y = AppContext.appBounds.height - bottomLayoutMargins - size.height - 60
|
||||||
|
newFrame = .init(x: (AppContext.appBounds.width - size.width) / 2, y: y, width: size.width, height: size.height)
|
||||||
|
}
|
||||||
|
return newFrame
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateWindowSize() {
|
||||||
|
guard let window = view.window as? CapsuleWindow else { return }
|
||||||
|
window.isUserInteractionEnabled = tapActionCallback != nil
|
||||||
|
let size = getWindowSize(window: window)
|
||||||
|
let newFrame = getWindowFrame(size: size)
|
||||||
|
window.transform = .identity
|
||||||
|
view.layoutIfNeeded()
|
||||||
|
UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut) {
|
||||||
|
window.frame = newFrame
|
||||||
|
window.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
if vm?.position == .top {
|
||||||
|
ToastWindow.updateToastWindowsLayout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,30 +43,11 @@ extension CapsuleTarget {
|
||||||
window = CapsuleWindow(capsule: self)
|
window = CapsuleWindow(capsule: self)
|
||||||
windows[position] = nil
|
windows[position] = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
window.isUserInteractionEnabled = tapActionCallback != nil
|
window.isUserInteractionEnabled = tapActionCallback != nil
|
||||||
// frame
|
|
||||||
let cardEdgeInsetsByDefault = config.cardEdgeInsetsByDefault
|
|
||||||
view.layoutIfNeeded()
|
|
||||||
var size = contentStack.frame.size
|
|
||||||
let width = min(config.cardMaxWidthByDefault, size.width + cardEdgeInsetsByDefault.left + cardEdgeInsetsByDefault.right)
|
|
||||||
let height = min(config.cardMaxHeightByDefault, size.height + cardEdgeInsetsByDefault.top + cardEdgeInsetsByDefault.bottom)
|
|
||||||
size = CGSize(width: width, height: max(height, config.cardMinHeight))
|
|
||||||
|
|
||||||
// 应用到frame
|
|
||||||
let newFrame: CGRect
|
|
||||||
switch vm?.position {
|
|
||||||
case .top, .none:
|
|
||||||
let topLayoutMargins = AppContext.appWindow?.safeAreaInsets.top ?? 8
|
|
||||||
let y = max(topLayoutMargins, 8)
|
|
||||||
newFrame = .init(x: (AppContext.appBounds.width - size.width) / 2, y: y, width: size.width, height: size.height)
|
|
||||||
case .middle:
|
|
||||||
newFrame = .init(x: (AppContext.appBounds.width - size.width) / 2, y: (AppContext.appBounds.height - size.height) / 2 - 20, width: size.width, height: size.height)
|
|
||||||
case .bottom:
|
|
||||||
let bottomLayoutMargins = AppContext.appWindow?.layoutMargins.bottom ?? 8
|
|
||||||
let y = AppContext.appBounds.height - bottomLayoutMargins - size.height - 60
|
|
||||||
newFrame = .init(x: (AppContext.appBounds.width - size.width) / 2, y: y, width: size.width, height: size.height)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
let size = getWindowSize(window: window)
|
||||||
|
let newFrame = getWindowFrame(size: size)
|
||||||
window.transform = .identity
|
window.transform = .identity
|
||||||
if isNew {
|
if isNew {
|
||||||
window.frame = newFrame
|
window.frame = newFrame
|
||||||
|
|
|
@ -87,13 +87,14 @@ extension ToastTarget: DefaultLayout {
|
||||||
bodyLabel.text = vm?.message
|
bodyLabel.text = vm?.message
|
||||||
view.layoutIfNeeded()
|
view.layoutIfNeeded()
|
||||||
|
|
||||||
|
setupImageView()
|
||||||
|
|
||||||
if isViewAppeared {
|
if isViewAppeared {
|
||||||
// 更新时间
|
// 更新时间
|
||||||
updateTimeoutDuration()
|
updateTimeoutDuration()
|
||||||
|
updateWindowSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
setupImageView()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadContentViewIfNeeded() {
|
func loadContentViewIfNeeded() {
|
||||||
|
@ -155,4 +156,55 @@ extension ToastTarget {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getWindowSize(window: ToastWindow) -> CGSize {
|
||||||
|
let cardEdgeInsets = config.cardEdgeInsetsByDefault
|
||||||
|
let width = CGFloat.minimum(AppContext.appBounds.width - config.marginX - config.marginX, config.cardMaxWidthByDefault)
|
||||||
|
view.frame.size = CGSize(width: width, height: config.cardMaxHeightByDefault) // 以最大高度开始布局,然后计算实际需要高度
|
||||||
|
titleLabel.sizeToFit()
|
||||||
|
bodyLabel.sizeToFit()
|
||||||
|
view.layoutIfNeeded()
|
||||||
|
// 更新子视图之后获取正确的高度
|
||||||
|
let height = calcHeight()
|
||||||
|
let size = CGSize(width: width, height: height)
|
||||||
|
view.frame.size = size
|
||||||
|
view.layoutIfNeeded()
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateWindowSize() {
|
||||||
|
guard let window = view.window as? ToastWindow else { return }
|
||||||
|
let lastSize = view.frame.size
|
||||||
|
let newSize = getWindowSize(window: window)
|
||||||
|
view.frame.size = lastSize
|
||||||
|
view.layoutIfNeeded()
|
||||||
|
window.frame.size = newSize
|
||||||
|
ToastWindow.updateToastWindowsLayout()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func calcHeight() -> CGFloat {
|
||||||
|
var height = CGFloat(0)
|
||||||
|
for v in infoStack.arrangedSubviews {
|
||||||
|
// 图片或者文本最大高度
|
||||||
|
height = CGFloat.maximum(v.frame.maxY, height)
|
||||||
|
}
|
||||||
|
if actionStack.arrangedSubviews.count > 0 {
|
||||||
|
height += actionStack.frame.height + contentStack.spacing
|
||||||
|
}
|
||||||
|
contentView.subviews.filter { v in
|
||||||
|
if v == contentMaskView {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if v == contentStack {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
} .forEach { v in
|
||||||
|
height = CGFloat.maximum(v.frame.maxY, height)
|
||||||
|
}
|
||||||
|
// 上下边间距
|
||||||
|
let cardEdgeInsets = config.cardEdgeInsetsByDefault
|
||||||
|
height += cardEdgeInsets.top + cardEdgeInsets.bottom
|
||||||
|
return height
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,32 +9,6 @@ import UIKit
|
||||||
|
|
||||||
extension ToastTarget {
|
extension ToastTarget {
|
||||||
|
|
||||||
private func calcHeight() -> CGFloat {
|
|
||||||
var height = CGFloat(0)
|
|
||||||
for v in infoStack.arrangedSubviews {
|
|
||||||
// 图片或者文本最大高度
|
|
||||||
height = CGFloat.maximum(v.frame.maxY, height)
|
|
||||||
}
|
|
||||||
if actionStack.arrangedSubviews.count > 0 {
|
|
||||||
height += actionStack.frame.height + contentStack.spacing
|
|
||||||
}
|
|
||||||
contentView.subviews.filter { v in
|
|
||||||
if v == contentMaskView {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if v == contentStack {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
} .forEach { v in
|
|
||||||
height = CGFloat.maximum(v.frame.maxY, height)
|
|
||||||
}
|
|
||||||
// 上下边间距
|
|
||||||
let cardEdgeInsets = config.cardEdgeInsetsByDefault
|
|
||||||
height += cardEdgeInsets.top + cardEdgeInsets.bottom
|
|
||||||
return height
|
|
||||||
}
|
|
||||||
|
|
||||||
@objc open func push() {
|
@objc open func push() {
|
||||||
guard ToastConfiguration.isEnabled else { return }
|
guard ToastConfiguration.isEnabled else { return }
|
||||||
let isNew: Bool
|
let isNew: Bool
|
||||||
|
@ -49,23 +23,14 @@ extension ToastTarget {
|
||||||
isNew = true
|
isNew = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// frame
|
|
||||||
let cardEdgeInsets = config.cardEdgeInsetsByDefault
|
|
||||||
let width = CGFloat.minimum(AppContext.appBounds.width - config.marginX - config.marginX, config.cardMaxWidthByDefault)
|
|
||||||
view.frame.size = CGSize(width: width, height: config.cardMaxHeightByDefault)
|
|
||||||
titleLabel.sizeToFit()
|
|
||||||
bodyLabel.sizeToFit()
|
|
||||||
view.layoutIfNeeded()
|
|
||||||
// 更新子视图之后获取正确的高度
|
|
||||||
let height = calcHeight()
|
|
||||||
view.frame.size = CGSize(width: width, height: height)
|
|
||||||
// 应用到frame
|
|
||||||
window.frame = CGRect(x: (AppContext.appBounds.width - width) / 2, y: 0, width: width, height: height)
|
|
||||||
window.rootViewController = self // 此时toast.view.frame.size会自动更新为window.frame.size
|
|
||||||
if windows.contains(window) == false {
|
if windows.contains(window) == false {
|
||||||
windows.append(window)
|
windows.append(window)
|
||||||
setContextWindows(windows)
|
setContextWindows(windows)
|
||||||
}
|
}
|
||||||
|
let size = getWindowSize(window: window)
|
||||||
|
window.frame = CGRect(x: (AppContext.appBounds.width - size.width) / 2, y: 0, width: size.width, height: size.height)
|
||||||
|
window.rootViewController = self // 此时toast.view.frame.size会自动更新为window.frame.size
|
||||||
|
|
||||||
ToastWindow.updateToastWindowsLayout(windows: windows)
|
ToastWindow.updateToastWindowsLayout(windows: windows)
|
||||||
// 为了更连贯,从进入动画开始时就开始计时
|
// 为了更连贯,从进入动画开始时就开始计时
|
||||||
updateTimeoutDuration()
|
updateTimeoutDuration()
|
||||||
|
|
Loading…
Reference in New Issue