【发布时间】:2021-02-28 07:05:05
【问题描述】:
我正在尝试添加一个应始终显示在主窗口顶部的横幅窗口。主窗口中的任何内容都不应阻止该横幅窗口上的内容,并且横幅窗口也不应阻止主窗口的内容。以下代码在 iPhone 上运行良好,但在启用了拆分视图的 iPad 上我遇到了一些问题。
我手动设置了两个窗口的框架,当我们在拆分视图中修改可用于场景的宽度时,当场景的宽度发生变化时,这会导致问题。
如何在拆分视图中观察应用场景的可用宽度变化?
我尝试了什么:
我尝试使用 viewWillLayoutSubviews、traitCollectionDidChange 以及 UIContentContainer 协议方法,如下面的代码所示,当我更改拆分视图上应用程序的可用宽度时,这些方法都不会被调用。只有在方向改变时才会调用它们。
项目的完整代码在这里https://github.com/anirudhbandi96/WindowTest
import UIKit
class ViewController: UIViewController {
let label: UILabel = {
let label = UILabel()
label.numberOfLines = 0
label.font = UIFont.preferredFont(forTextStyle: .largeTitle)
label.textAlignment = .center
label.textColor = .white
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.backgroundColor = .systemGreen
label.text = "This is the key window"
view.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
label.centerXAnchor.constraint(equalTo: view.centerXAnchor),
label.topAnchor.constraint(equalTo: view.topAnchor),
label.leadingAnchor.constraint(equalTo: view.leadingAnchor),
label.trailingAnchor.constraint(equalTo: view.trailingAnchor)
])
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
print("laying out subviews")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Just added a small delay to see the addition of the banner window clearly
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
// height of the Banner window
let height: CGFloat = 100
guard let window = self.view.window,
let windowScene = window.windowScene,
let keyWindow = windowScene.windows.first(where: { $0.isKeyWindow })
else { return }
// accessing the key window and changing its frame so that the window's content is not
// blocked by the banner window that is going to be above it
let size = keyWindow.frame.size
keyWindow.frame = CGRect(origin: CGPoint(x: 0, y: height), size: CGSize(width: size.width, height: size.height - height))
// Creating a banner window
let bannerWindow = UIWindow(windowScene: windowScene)
bannerWindow.frame = CGRect(origin: .zero, size: CGSize(width: size.width, height: height))
bannerWindow.isHidden = false
// Creating a banner view and adding it to the banner window
let bannerView = UIView(frame: .zero)
bannerView.backgroundColor = .systemPink
bannerView.translatesAutoresizingMaskIntoConstraints = false
bannerWindow.addSubview(bannerView)
bannerWindow.windowLevel = keyWindow.windowLevel + 1
NSLayoutConstraint.activate([
bannerView.leadingAnchor.constraint(equalTo: bannerWindow.leadingAnchor),
bannerView.trailingAnchor.constraint(equalTo: bannerWindow.trailingAnchor),
bannerView.heightAnchor.constraint(equalToConstant: height),
bannerView.bottomAnchor.constraint(equalTo: bannerWindow.bottomAnchor),
])
// Keeping a reference to the banner window to prevent it from being deallocated
appDelegate.bannerWindow = bannerWindow
}
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
print("Trait collection changed")
}
override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
super.willTransition(to: newCollection, with: coordinator)
print("will transition to new collection")
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
print("will transtion to size: \(size)")
}
}
启用分屏后,它仍然使用之前为全屏设置的帧,这是有意义的。
【问题讨论】:
标签: ios swift ipad uikit ipados