我的导航栏有一个white
backgroundColor
,我的状态栏使用dark
textColor
. 当用户将 iOS 主题更改为深色模式时,状态栏将变为背景white
上的文本。white
结果,我什么都看不见。如何为我的应用禁用此更改?
9 回答
iOS 13 解决方案
UINavigationController
是 的子类UIViewController
!(谁知道 )
因此,当呈现嵌入在导航控制器中的视图控制器时,您并没有真正呈现嵌入的视图控制器。您正在展示导航控制器!UINavigationController
, 作为 , 的子类UIViewController
, 继承preferredStatusBarStyle
和childForStatusBarStyle
, 您可以根据需要进行设置。
以下任何一种方法都应该有效:
完全退出黑暗模式
- 在您的
info.plist
中,添加以下属性:- 键 -
UIUserInterfaceStyle
(又名“用户界面风格”) - 价值 - 光
- 键 -
- 在您的
覆盖
preferredStatusBarStyle
范围内UINavigationController
preferredStatusBarStyle
( doc ) - 视图控制器的首选状态栏样式子类
或扩展UINavigationController
class MyNavigationController: UINavigationController { override var preferredStatusBarStyle: UIStatusBarStyle { .lightContent } }
或者extension UINavigationController { open override var preferredStatusBarStyle: UIStatusBarStyle { .lightContent } }
覆盖
childForStatusBarStyle
范围内UINavigationController
childForStatusBarStyle
( doc ) - 当系统需要视图控制器用于确定状态栏样式时调用- 根据苹果的文档,
“如果您的容器视图控制器从其子视图控制器之一派生其状态栏样式,[覆盖此属性]并返回该子视图控制器。如果您返回 nil 或不覆盖此方法,则使用 self 的状态栏样式. 如果此方法的返回值发生变化,请调用 setNeedsStatusBarAppearanceUpdate() 方法。"
换句话说,如果您在此处不执行解决方案 3,系统将回退到上面的解决方案 2。
子类
或扩展UINavigationController
class MyNavigationController: UINavigationController { override var childForStatusBarStyle: UIViewController? { topViewController } }
或者extension UINavigationController { open override var childForStatusBarStyle: UIViewController? { topViewController } }
您可以在上面返回您想要的任何视图控制器。我推荐以下之一:
注意:如果您决定子类UINavigationController
化,请记住通过 IB 中的身份检查器将该类应用于您的导航控制器。
编辑:删除线编辑已删除扩展作为建议的答案。其他开发人员指出,他们停止在 Xcode 11.4 中工作,Apple 的文档不鼓励使用这种模棱两可的行为。
PS 我的代码使用 Swift 5.1 语法
如果您将UIViewControllerBasedStatusBarAppearance
应用程序中的键设置info.plist
为YES
,则可以覆盖当前呈现的视图控制器中的状态栏样式:
override var preferredStatusBarStyle: UIStatusBarStyle {
if #available(iOS 13, *) {
return .darkContent
} else {
return .default
}
}
并调用 setNeedsStatusBarAppearanceUpdate() 方法
您可以将扩展名写入UIStatusBarStyle
:
extension UIStatusBarStyle {
static var black: UIStatusBarStyle {
if #available(iOS 13.0, *) {
return .darkContent
}
return .default
}
}
然后您可以轻松地在您的 ViewControllers 中使用:
override var preferredStatusBarStyle: UIStatusBarStyle {
.black
}
您可以尝试使您的导航栏始终light
if #available(iOS 13.0, *) {
navigationController?.navigationBar.overrideUserInterfaceStyle = .light
}
我做过这样的事情。
我有切换器功能,根据显示的视图控制器切换状态栏样式
func toggleLight() {
self.navigationBar.barTintColor = AppColors.White
isDarkStyle = false
setNeedsStatusBarAppearanceUpdate()
}
这是最重要的部分
override var preferredStatusBarStyle: UIStatusBarStyle {
if #available(iOS 13.0, *) {
return isDarkStyle ? .lightContent : .darkContent
}
return isDarkStyle ? .lightContent : .default
}
其中 isDarkStyle 代表导航栏背景颜色深或浅。如果它是暗的,那么文本(内容)应该是亮的,如果它是亮的,那么文本(内容)应该是默认的或者从 iOS 13 开始是暗的。
总结一下:.lightContent, .darkContent
显示独立于暗模式,就像它应该做的那样。虽然.default
容易受到暗模式更改的影响!
如果您使用 aUINavigationController
,preferredStatusBarStyle
请像这样覆盖扩展(或您自己的子类)中的 (仅preferredStatusBarStyle
在您的视图控制器中覆盖是行不通的):
extension UINavigationController {
override open var preferredStatusBarStyle: UIStatusBarStyle {
guard #available(iOS 13, *) else {
return .default
}
return .darkContent
}
}
正如弗兰克所说,UIViewControllerBasedStatusBarAppearance
必须YES
在你的info.plist
此扩展可帮助您更改状态栏文本颜色并支持 iOS 13 https://stackoverflow.com/a/59767435/10512612
如果其他人发现上述答案都不起作用(就像我所做的那样),那么如果您在UIWindowScene
其中有多个窗口,它将使用最顶部的窗口而不是关键窗口来确定状态栏的外观,则存在一个非常具体的边缘情况。
因此,例如,如果您的键窗口windowLevel
设置为 to1
和辅助窗口windowLevel
设置为1.1
,UIKit 将(无论出于何种原因)询问辅助窗口中的视图控制器的状态栏外观,而不是键中的视图控制器窗口,即使它的 alpha 为 0。
我们的解决方法是仅在辅助窗口处于活动状态时将其置于较高级别,并在其隐藏时将其降低到关键窗口下方。
有两种方法可以解决这个问题。在 UINavigationController 后代类中定义 childViewControllerForStatusBarStyle 函数:
@interface MyNavigationController : UINavigationController
...
@end
@implementation MyNavigationController
...
- (UIViewController *)childViewControllerForStatusBarStyle
{
return self.topViewController;
}
...
@end
之后,您需要为每个控制器添加函数 preferredStatusBarStyle。
第二个选项是为所有控制器定义 preferredStatusBarStyle 函数。但是这个函数不应该位于根控制器中,而应该位于 UINavigationController 的后代类中。
@interface MyNavigationController : UINavigationController
...
@end
@implementation MyNavigationController
...
- (UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
...
@end
但是,即使在这种情况下,也有必要为所有隐藏导航栏的控制器(如果有)定义函数 preferredStatusBarStyle。