更新视图控制器之间的状态栏样式

问题描述 投票:5回答:4

在我的info.plist,文件我有View controller-based status bar appearance设置为YES

我有一个隐藏状态栏的FirstViewController

在我的SecondViewController我有

override var preferredStatusBarStyle: UIStatusBarStyle {
    return .lightContent
}

override var prefersStatusBarHidden: Bool {
    return false
}

override func viewDidLoad() {
    super.viewDidLoad()

    setNeedsStatusBarAppearanceUpdate()
}

但是,状态栏显示,但是显示为黑色。

如何让它正确更新?谢谢

编辑:

AppDelegate.swift也有这个

UIApplication.shared.statusBarStyle = .lightContentdidFinishLaunchingWithOptions

ios swift statusbar
4个回答
10
投票

当您的视图控制器是导航控制器的子节点时,有关如何管理状态栏样式的问题有很多误解。

您的子视图控制器可以实现preferredStatusBarStyle,如果导航栏被隐藏,这将正常工作。

如果显示导航栏,导航控制器将根据导航栏的barStyle设置状态栏样式 - 如果栏样式为.default则设置为.default,如果栏样式为.lightContent则设置为.black。因此,当导航栏显示时,视图控制器设置状态栏样式的正确方法是设置导航控制器的导航栏样式。

显而易见的地方是viewWillAppear,只要这个视图控制器成为导航控制器堆栈的顶部,就会调用它:

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationController?.navigationBar.barStyle = .black // or .default
}

19
投票

Info.plist文件中有一个名为View controller-based状态栏外观的属性。它应该设置为YES。然后在你的UIViewController中你应该覆盖preferredStatusBarStyle

override var preferredStatusBarStyle : UIStatusBarStyle {
    return .lightContent
}

需要注意的一件重要事情是:如果您将视图控制器嵌入到UINavigationController中并且您的视图控制器的preferredStatusBarStyle方法未被调用 - 您将必须通过编写如下内容来解决此问题:

extension UINavigationController {
    override open var preferredStatusBarStyle : UIStatusBarStyle {
        return topViewController?.preferredStatusBarStyle ?? .default
    }
}

它的作用只是向顶级控制器询问其状态栏样式,并进行适当更新


0
投票

UINavigationController有另一种解决方案。您可以将其子类化并使用childForStatusBarHidden属性与setNeedsStatusBarAppearanceUpdate()结合使用。

class StatusBarNavigationController: UINavigationController {
    override var childForStatusBarHidden: UIViewController? {
        return topViewController
    }

    override var viewControllers: [UIViewController] {
        didSet { setNeedsStatusBarAppearanceUpdate() }
    }
}

所以状态栏样式将由topViewController定义。


0
投票

Swift 5,iOS 12

这里的大部分答案都很有帮助,但并未立即为我解决问题。我有一个嵌套结构(根VC>标签栏VC>导航VC>特定页面VC),我希望其中一个推送页面VC更改状态栏颜色。

在页面VC中设置navigationBar.barStyle对我没有任何帮助,可能是因为导航VC不是顶级VC。设置preferredStatusBarStyle在页面VC中也不起作用(尽管如果我在根VC中覆盖此属性,它确实有效)。

@kelin的回答让我朝着正确的方向前进。 childForStatusBarStyle帮助指定应该检查哪个子VC的正确样式。以下是我采取的步骤:

步骤1:为我的VC层次结构中的所有VC实现childForStatusBarHidden

例如对于根VC

override var childForStatusBarStyle: UIViewController? {
  // this is a custom var I've set up
  return currentViewController
}

对于选项卡VC

override var childForStatusBarStyle: UIViewController? {
  return selectedViewController
}

对于导航VC

override var childForStatusBarStyle: UIViewController? {
  return topViewController
}

第2步:确保正确调用childForStatusBarStyle。我的根VC的currentViewController变量在iOS检查之前没有设置,所以我需要在设置该变量后调用setNeedsStatusBarAppearanceUpdate()以指示需要再次检查childForStatusBarStyle

步骤3:在确定状态栏外观的子VC中,覆盖样式:

override var preferredStatusBarStyle: UIStatusBarStyle {
  return .lightContent
}

步骤4:确保在创建子VC时调用setNeedsStatusBarAppearanceUpdate(),并从根控制器调用它。所以,孩子VC中的setNeedsStatusBarAppearanceUpdate()没有用,但是UIApplication.shared.keyWindow?.rootViewController?.setNeedsStatusBarAppearanceUpdate()做了。

步骤5:当从层次结构中移除子VC并且您想要恢复状态栏样式时,请务必再次从根VC调用setNeedsStatusBarAppearanceUpdate(),可能在viewWillDisappear中。

作为旁注,上面的解决方案并不要求我明确地将View controller-based status bar appearance Info.plist值设置为许多答案引用的YES

© www.soinside.com 2019 - 2024. All rights reserved.