维护添加到 KeyWindow 的自定义 UIView
Posted
技术标签:
【中文标题】维护添加到 KeyWindow 的自定义 UIView【英文标题】:Maintain custom UIView that is added to KeyWindow 【发布时间】:2019-08-30 08:22:54 【问题描述】:我正在为我的应用开发同步功能。
我想要实现的是显示一个自定义 UIView,它将作为用户的指示器,无论用户在哪里(例如导航到仪表板、设置、个人资料页面等),同步正在进行中.短期内,它会静态地固定在应用内的某个位置。
在网上做了一些研究后,我得出结论使用keyWindow并为其添加一个子视图。
这是我的代码
override func viewDidAppear(_ animated: Bool)
super.viewDidAppear(animated)
if let window = UIApplication.shared.keyWindow
window.windowLevel = .statusBar
let uiView = UIView()
uiView.backgroundColor = .green
window.addSubview(uiView)
uiView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
uiView.heightAnchor.constraint(equalToConstant: 150),
uiView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 25),
uiView.topAnchor.constraint(equalTo: view.topAnchor, constant: 150),
uiView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.4)
])
以上代码运行良好,我可以将自定义视图附加到 keyWindow。但是,当用户导航到另一个屏幕时,添加的 customView 将消失,并且仅在用户返回上一个屏幕时显示。
有人可以指导我缺少哪一部分吗?我在哪部分做错了?
谢谢
【问题讨论】:
这取决于您希望用户交互如何工作。我会先尝试添加另一个窗口;与制作自定义警报视图相同。或者更简单的方法可能只为您工作,通过操作layer.zPosition
来更改自定义视图的 Z 顺序。
嗨@MaticOblak,感谢您的回复。您介意就如何添加另一个窗口提供一些见解吗?我不太确定那是什么。谢谢.. :)
【参考方案1】:
根据 cmets,我添加了创建新窗口的最低要求,该窗口现在可以始终位于您的视图控制器甚至其他窗口的顶部:
class OverlayViewController: UIViewController
private var myWindow: UIWindow? // Our own window needs to be retained
override func viewDidLoad()
super.viewDidLoad()
view.backgroundColor = UIColor.black.withAlphaComponent(0.3)
view.addSubview(
let label = UILabel(frame: .zero)
label.text = "This is an overlay."
label.sizeToFit()
label.center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
return label
())
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onTap)))
@objc private func onTap()
myWindow?.isHidden = true
myWindow?.removeFromSuperview()
myWindow = nil
static func showInNewWindow()
let window = UIWindow(frame: UIScreen.main.bounds)
// window.windowLevel = .alert
// window.isUserInteractionEnabled = false
window.rootViewController =
let controller = OverlayViewController() // OR UIStoryboard(name: "<#FileName#>", bundle: nil).instantiateViewController(withIdentifier: "<#Storyboard Identifier#>")
controller.myWindow = window
return controller
()
window.makeKeyAndVisible()
所以这只是全代码的简单视图控制器示例,只需调用OverlayViewController.showInNewWindow()
即可在项目的任何地方使用它。视图控制器可以来自故事板。
有趣的部分是showInNewWindow
,它创建了一个新窗口和这个视图控制器的一个实例,它被设置为一个根视图控制器。要显示新窗口,您只需拨打makeKeyAndVisible
。要删除它,只需隐藏它并将其从超级视图中删除,就像在onTap
中所做的那样。在这种情况下,该窗口由应创建保留周期的视图控制器引用。似乎这是强制性的。这也意味着我们需要在通过调用myWindow = nil
关闭窗口后进行一些清理。
还有一些可能的设置,例如您可以禁用用户交互并允许用户仍然使用此窗口下方的窗口 (window.isUserInteractionEnabled = false
)。您可以设置窗口的级别,以显示它的显示位置(window.windowLevel = .alert
)。您可以使用这些值进行一些操作。设置哪个取决于您希望窗口的级别。
【讨论】:
非常感谢您的详细解释!真的很感激 Btw Matic,makeKeyAndVisible() 是否等同于 isHidden = false? @Alvin 我不这么认为。我认为它在后面做了一些额外的工作,比如将自己注册为关键窗口,我认为这是应用程序的一个属性。我相信根据文档,必须调用它。 知道了。非常感谢 Matic以上是关于维护添加到 KeyWindow 的自定义 UIView的主要内容,如果未能解决你的问题,请参考以下文章
UIGesture 返回 UIImageView 而不是自定义视图
UIAlertViews、UIActionSheets 和 keyWindow 问题