【发布时间】:2020-11-15 11:15:12
【问题描述】:
我已经花了很多时间试图找出一种方法,使用新的生命周期 SwiftUI 应用程序将 statusBarStyle 更改为亮/暗。
关于状态栏的最新帖子教如何隐藏它,但我不想这样做,我只需要将其更改为深色或浅色。
要更改颜色,我发现的最新方法是打开 SceneDelegate.swift 并更改 window.rootViewController 以使用我自己的 HostingController ,但它仅适用于使用 UIKit App Delegate Lifecycle 的项目。使用SwiftUI App Lifecycle,不会生成SceneDelegate.swift,请问在哪里做呢?
我可以通过 Xcode 界面上的常规设置来完成。我的问题是关于如何通过代码动态地做到这一点。
- 目标:iOS 14
- IDE:Xcode 12 beta 3
- 操作系统:MacOS 11 Big Sur
以下是我目前得到的。
Everything.swift
import Foundation
import SwiftUI
class LocalStatusBarStyle { // style proxy to be stored in Environment
fileprivate var getter: () -> UIStatusBarStyle = { .default }
fileprivate var setter: (UIStatusBarStyle) -> Void = {_ in}
var currentStyle: UIStatusBarStyle {
get { self.getter() }
set { self.setter(newValue) }
}
}
struct LocalStatusBarStyleKey: EnvironmentKey {
static let defaultValue: LocalStatusBarStyle = LocalStatusBarStyle()
}
extension EnvironmentValues { // Environment key path variable
var localStatusBarStyle: LocalStatusBarStyle {
get {
return self[LocalStatusBarStyleKey.self]
}
}
}
class MyHostingController<Content>: UIHostingController<Content> where Content:View {
private var internalStyle = UIStatusBarStyle.default
@objc override dynamic open var preferredStatusBarStyle: UIStatusBarStyle {
get {
internalStyle
}
set {
internalStyle = newValue
self.setNeedsStatusBarAppearanceUpdate()
}
}
override init(rootView: Content) {
super.init(rootView:rootView)
LocalStatusBarStyleKey.defaultValue.getter = { self.preferredStatusBarStyle }
LocalStatusBarStyleKey.defaultValue.setter = { self.preferredStatusBarStyle = $0 }
}
@objc required dynamic init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
struct TitlePage: View {
@Environment(\.localStatusBarStyle) var statusBarStyle
@State var title: String
var body: some View {
Text(title).onTapGesture {
if self.statusBarStyle.currentStyle == .darkContent {
self.statusBarStyle.currentStyle = .default
self.title = "isDefault"
} else {
self.statusBarStyle.currentStyle = .darkContent
self.title = "isDark"
}
}
}
}
struct ContainerView: View {
var controllers: [MyHostingController<TitlePage>]
init(_ titles: [String]) {
self.controllers = titles.map { MyHostingController(rootView: TitlePage(title: $0)) }
}
var body: some View {
PageViewController(controllers: self.controllers)
}
}
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal)
return pageViewController
}
func updateUIViewController(_ uiViewController: UIPageViewController, context: Context) {
uiViewController.setViewControllers([controllers[0]], direction: .forward, animated: true)
}
typealias UIViewControllerType = UIPageViewController
}
MyApp.swift
import SwiftUI
@main
struct TestAppApp: App {
var body: some Scene {
WindowGroup {
ContainerView(["Subscribe", "Comment"])
}
}
}
struct TestAppApp_Previews: PreviewProvider {
static var previews: some View {
Text("Hello, World!")
}
}
【问题讨论】:
-
您可以将自己的
statusBarStyle定义为@EnvironmentKey属性。这将在您的第一个视图上定义,所有子视图都将继承此属性。这个答案可能会有所帮助:stackoverflow.com/questions/59569503/… -
感谢您的评论。要执行您链接的内容,我需要访问场景委托,这正是我所说的我无权访问,因为没有创建。你知道如何在没有 SceneDelegate.swift 的情况下访问这个委托吗?
-
如果你需要一些 UIKit 级别的自定义,你应该使用 UIKit 生命周期。实际上,目前 SwiftUI 生命周期根本无法配置。从行为的角度来看,这些方法之间没有区别,SwiftUI Life Cycle 只是场景管理的内置包装器。
-
Asperi,我会照你说的做。我将使用 UIKit 生命周期为 iOS 创建一个新项目,并为 MacOS 创建一个新项目。 SwiftUI Life Cycle 没有准备好,或者文档还不够完善。
-
@MoacirBraga 你有没有找到使用 SwiftUI App Lifecycle 以编程方式更改状态栏颜色的解决方案?
标签: ios swift colors swiftui statusbar