Swift:将自定义警报视图置于导航栏之上
Swift: Bring custom alert view over nav bar
我在我的应用程序中使用 UIView 作为警报视图,并且我想在设备未连接到互联网时将其显示为屏幕顶部的横幅。所以我的问题是这个视图出现在我的导航栏下,我怎样才能把它放在前面?我已经试过了UIApplication.shared.keyWindow!并将我的 backgroundView 作为子视图添加到其中,但这会导致其他问题。
这是我的警报视图class:我会提供所有class,但我的实现是在 show() 方法中。
import Foundation
import UIKit
import SnapKit
class ConnectionAlertView: UIView, UIGestureRecognizerDelegate {
internal var backgroundView: UIView = {
let view = UIView()
view.backgroundColor = Theme.Color.alertLabelBackgroundColor
view.alpha = 0
view.layer.cornerRadius = 15
return view
}()
internal var dismissButton: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "close_icon")
imageView.layer.cornerRadius = 15
imageView.isUserInteractionEnabled = true
return imageView
}()
internal var descriptionTitleLabel: UILabel = {
let label = UILabel()
label.text = "Відсутнє підключення до Інтернету"
label.font = Theme.Font.fontBodyLarge
label.textColor = .white
return label
}()
internal var descriptionLabel: UILabel = {
let label = UILabel()
label.text = "Перевірте налаштування мережі"
label.font = Theme.Font.fontBodyMedium
label.textColor = .white
return label
}()
// MARK: - Private Methods -
internal func layout() {
backgroundView.addSubview(descriptionTitleLabel)
backgroundView.addSubview(descriptionLabel)
backgroundView.addSubview(dismissButton)
descriptionTitleLabel.snp.makeConstraints { make in
make.trailing.equalTo(backgroundView).offset(54)
make.leading.equalTo(backgroundView).offset(16)
make.top.equalTo(backgroundView).offset(12)
}
descriptionLabel.snp.makeConstraints { make in
make.leading.equalTo(descriptionTitleLabel.snp.leading)
make.top.equalTo(descriptionTitleLabel.snp.bottom).offset(4)
}
dismissButton.snp.makeConstraints { make in
make.width.height.equalTo(30)
make.centerY.equalTo(backgroundView)
make.trailing.equalTo(backgroundView).offset(-16)
}
}
internal func configure() {
let tap = UITapGestureRecognizer(target: self, action: #selector(dismiss(sender:)))
tap.delegate = self
dismissButton.addGestureRecognizer(tap)
}
// MARK: - Public Methods -
func show(viewController: UIViewController) {
guard let targetView = viewController.view else { return }
backgroundView.frame = CGRect(x: 10, y: 50, width: targetView.frame.width - 20 , height: 67)
targetView.addSubview(targetView)
layout()
configure()
// show view
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
UIView.transition(with: self.backgroundView, duration: 0.6,
options: .transitionCrossDissolve,
animations: {
self.backgroundView.alpha = 1
})
}
// hide view after 5 sec delay
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
UIView.transition(with: self.backgroundView, duration: 1,
options: .transitionCrossDissolve,
animations: {
self.backgroundView.alpha = 0
})
}
}
// MARK: - Objc Methods -
@objc internal func dismiss(sender: UITapGestureRecognizer) {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
UIView.transition(with: self.backgroundView, duration: 1,
options: .transitionCrossDissolve,
animations: {
self.backgroundView.alpha = 0
})
}
}
}
我的viewController:
class PhoneNumViewController: UIViewController {
let alert = ConnectionAlertView()
private func checkInternetConnection() {
if !NetworkingMonitor.isConnectedToInternet {
log.error("No internet connection!")
alert.show(viewController: self)
}
}
}
由于您有一个导航控制器并且不希望将此视图直接添加到 window,我可以提供以下可行的想法。
您的 UIViewController 包含在 UINavigationController 中,因此如果您将警报添加到 UIViewController,您会在 UINavigationBar 下方注意到它。
您可以改为通过以下更改显示来自 UINavigationController 的警报。
1.
在你的 class ConnectionAlertView: UIView
中的 func show(viewController: UIViewController)
我更改了以下行:
targetView.addSubview(targetView)
到
targetView.addSubview(backgroundView)
这与您的问题没有直接关系,但似乎是一个错误并导致崩溃,因为您似乎想在目标视图上添加背景视图。
2.
在你的 class ViewController: UIViewController
中,当你想显示你的警报视图时,像这样传递 UINavigationController:
if let navigationController = self.navigationController
{
alert.show(viewController: navigationController)
}
我相信这应该会给你想要的结果(图像和字体看起来不同,因为我没有这些文件,但在你这边应该可以正常工作):
我在我的应用程序中使用 UIView 作为警报视图,并且我想在设备未连接到互联网时将其显示为屏幕顶部的横幅。所以我的问题是这个视图出现在我的导航栏下,我怎样才能把它放在前面?我已经试过了UIApplication.shared.keyWindow!并将我的 backgroundView 作为子视图添加到其中,但这会导致其他问题。
这是我的警报视图class:我会提供所有class,但我的实现是在 show() 方法中。
import Foundation
import UIKit
import SnapKit
class ConnectionAlertView: UIView, UIGestureRecognizerDelegate {
internal var backgroundView: UIView = {
let view = UIView()
view.backgroundColor = Theme.Color.alertLabelBackgroundColor
view.alpha = 0
view.layer.cornerRadius = 15
return view
}()
internal var dismissButton: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "close_icon")
imageView.layer.cornerRadius = 15
imageView.isUserInteractionEnabled = true
return imageView
}()
internal var descriptionTitleLabel: UILabel = {
let label = UILabel()
label.text = "Відсутнє підключення до Інтернету"
label.font = Theme.Font.fontBodyLarge
label.textColor = .white
return label
}()
internal var descriptionLabel: UILabel = {
let label = UILabel()
label.text = "Перевірте налаштування мережі"
label.font = Theme.Font.fontBodyMedium
label.textColor = .white
return label
}()
// MARK: - Private Methods -
internal func layout() {
backgroundView.addSubview(descriptionTitleLabel)
backgroundView.addSubview(descriptionLabel)
backgroundView.addSubview(dismissButton)
descriptionTitleLabel.snp.makeConstraints { make in
make.trailing.equalTo(backgroundView).offset(54)
make.leading.equalTo(backgroundView).offset(16)
make.top.equalTo(backgroundView).offset(12)
}
descriptionLabel.snp.makeConstraints { make in
make.leading.equalTo(descriptionTitleLabel.snp.leading)
make.top.equalTo(descriptionTitleLabel.snp.bottom).offset(4)
}
dismissButton.snp.makeConstraints { make in
make.width.height.equalTo(30)
make.centerY.equalTo(backgroundView)
make.trailing.equalTo(backgroundView).offset(-16)
}
}
internal func configure() {
let tap = UITapGestureRecognizer(target: self, action: #selector(dismiss(sender:)))
tap.delegate = self
dismissButton.addGestureRecognizer(tap)
}
// MARK: - Public Methods -
func show(viewController: UIViewController) {
guard let targetView = viewController.view else { return }
backgroundView.frame = CGRect(x: 10, y: 50, width: targetView.frame.width - 20 , height: 67)
targetView.addSubview(targetView)
layout()
configure()
// show view
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
UIView.transition(with: self.backgroundView, duration: 0.6,
options: .transitionCrossDissolve,
animations: {
self.backgroundView.alpha = 1
})
}
// hide view after 5 sec delay
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
UIView.transition(with: self.backgroundView, duration: 1,
options: .transitionCrossDissolve,
animations: {
self.backgroundView.alpha = 0
})
}
}
// MARK: - Objc Methods -
@objc internal func dismiss(sender: UITapGestureRecognizer) {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
UIView.transition(with: self.backgroundView, duration: 1,
options: .transitionCrossDissolve,
animations: {
self.backgroundView.alpha = 0
})
}
}
}
我的viewController:
class PhoneNumViewController: UIViewController {
let alert = ConnectionAlertView()
private func checkInternetConnection() {
if !NetworkingMonitor.isConnectedToInternet {
log.error("No internet connection!")
alert.show(viewController: self)
}
}
}
由于您有一个导航控制器并且不希望将此视图直接添加到 window,我可以提供以下可行的想法。
您的 UIViewController 包含在 UINavigationController 中,因此如果您将警报添加到 UIViewController,您会在 UINavigationBar 下方注意到它。
您可以改为通过以下更改显示来自 UINavigationController 的警报。
1.
在你的 class ConnectionAlertView: UIView
中的 func show(viewController: UIViewController)
我更改了以下行:
targetView.addSubview(targetView)
到
targetView.addSubview(backgroundView)
这与您的问题没有直接关系,但似乎是一个错误并导致崩溃,因为您似乎想在目标视图上添加背景视图。
2.
在你的 class ViewController: UIViewController
中,当你想显示你的警报视图时,像这样传递 UINavigationController:
if let navigationController = self.navigationController
{
alert.show(viewController: navigationController)
}
我相信这应该会给你想要的结果(图像和字体看起来不同,因为我没有这些文件,但在你这边应该可以正常工作):