使用 UIHostingController 时状态栏是透明的
Status Bar is transparent with UIHostingController
以下是我在真实项目中遇到的问题的简化项目。
我有一个项目,我在其中添加了一个带有 UIHostingController 的 SwiftUI 视图,并且顶部的状态栏是透明的。我在滚动 SwiftUI 视图时看到它。
重新创建很容易,使用情节提要创建一个新的 iOS 项目,并使用 NavigationView 将 ViewController
嵌入情节提要中。
然后将 ViewController
内容替换为:
import UIKit
import SwiftUI
final class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let hostingController = UIHostingController(rootView: ScrollView { MySwiftUIView() })
self.addChild(hostingController)
view.addSubview(hostingController.view)
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
hostingController.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
hostingController.view.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
hostingController.view.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.backgroundColor = UIColor.yellow
self.title = "MyTitle"
}
}
struct MySwiftUIView: View {
var body: some View {
ZStack {
Color.green
ScrollView {
VStack {
ForEach(0...100, id: \.self) { index in
Text("This is line \(index)")
}
}
}
}
}
}
状态栏是透明的,显示视图的白色背景:
当我开始滚动 MySwiftUIView
时,状态栏是透明的更加明显:
我四处寻找解决方案,因为我希望状态栏具有与导航栏相同的颜色,并且不在状态栏中显示来自 SwiftUI 视图的内容。但是到目前为止我还没有找到解决办法。
尝试更改:
hostingController.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
至
hostingController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
我不确定,这是您的预期结果,但它确实消除了 SwiftUI
内容重叠。
这也是一招:
func setStatusBar() {
if #available(iOS 13, *)
{
let keyWindow = UIApplication.shared.connectedScenes
.filter({[=10=].activationState == .foregroundActive})
.compactMap({[=10=] as? UIWindowScene})
.first?.windows
.filter({[=10=].isKeyWindow}).first
let statusBar = UIView(frame: (keyWindow?.windowScene?.statusBarManager?.statusBarFrame) ?? CGRect(x: 0, y: 0, width: screenWidth, height: statubarHeight))
statusBar.backgroundColor = .green
keyWindow?.addSubview(statusBar)
} else {
let statusBar: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
if statusBar.responds(to:#selector(setter: UIView.backgroundColor)) {
statusBar.backgroundColor = .green
}
UIApplication.shared.statusBarStyle = .lightContent
}
}
以下是我在真实项目中遇到的问题的简化项目。
我有一个项目,我在其中添加了一个带有 UIHostingController 的 SwiftUI 视图,并且顶部的状态栏是透明的。我在滚动 SwiftUI 视图时看到它。
重新创建很容易,使用情节提要创建一个新的 iOS 项目,并使用 NavigationView 将 ViewController
嵌入情节提要中。
然后将 ViewController
内容替换为:
import UIKit
import SwiftUI
final class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let hostingController = UIHostingController(rootView: ScrollView { MySwiftUIView() })
self.addChild(hostingController)
view.addSubview(hostingController.view)
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
hostingController.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
hostingController.view.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
hostingController.view.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.backgroundColor = UIColor.yellow
self.title = "MyTitle"
}
}
struct MySwiftUIView: View {
var body: some View {
ZStack {
Color.green
ScrollView {
VStack {
ForEach(0...100, id: \.self) { index in
Text("This is line \(index)")
}
}
}
}
}
}
状态栏是透明的,显示视图的白色背景:
当我开始滚动 MySwiftUIView
时,状态栏是透明的更加明显:
我四处寻找解决方案,因为我希望状态栏具有与导航栏相同的颜色,并且不在状态栏中显示来自 SwiftUI 视图的内容。但是到目前为止我还没有找到解决办法。
尝试更改:
hostingController.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
至
hostingController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
我不确定,这是您的预期结果,但它确实消除了 SwiftUI
内容重叠。
这也是一招:
func setStatusBar() {
if #available(iOS 13, *)
{
let keyWindow = UIApplication.shared.connectedScenes
.filter({[=10=].activationState == .foregroundActive})
.compactMap({[=10=] as? UIWindowScene})
.first?.windows
.filter({[=10=].isKeyWindow}).first
let statusBar = UIView(frame: (keyWindow?.windowScene?.statusBarManager?.statusBarFrame) ?? CGRect(x: 0, y: 0, width: screenWidth, height: statubarHeight))
statusBar.backgroundColor = .green
keyWindow?.addSubview(statusBar)
} else {
let statusBar: UIView = UIApplication.shared.value(forKey: "statusBar") as! UIView
if statusBar.responds(to:#selector(setter: UIView.backgroundColor)) {
statusBar.backgroundColor = .green
}
UIApplication.shared.statusBarStyle = .lightContent
}
}