UIStatusBarStyle PreferredStatusBarStyle在iOS 7上不起作用

And*_*ith 110 iphone uistatusbar ios7 xcode5

在我使用Xcode 5 for iOS 7构建的iPhone应用程序UIViewControllerBasedStatusBarAppearance=YESinfo.plist,我设置了ViewController这个代码:

-(UIStatusBarStyle) preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}
Run Code Online (Sandbox Code Playgroud)

但状态栏在黑色背景下仍然是黑色的.

我知道它可以通过设置这个程序范围的更改UIViewControllerBasedStatusBarAppearance=NOinfo.plist,但我确实需要改变这种对viewControllerviewController基础在运行时.

mxc*_*xcl 279

我发现如果您的ViewController在navigationController中,那么navigationController将navigationBar.barStyle确定statusBarStyle.

将navigationBar设置barStyleUIBarStyleBlackTranslucent将提供白色状态栏文本(即.UIStatusBarStyleLightContent),UIBarStyleDefault并将提供黑色状态栏文本(即.UIStatusBarStyleDefault).

请注意,即使您通过其完全更改navigationBar的颜色,这也适用barTintColor.

  • 这对我没有意义,但它有效!谢谢. (21认同)
  • 我相信这是因为`UINavigationController`的`preferredStatusBarStyle`没有调用它所托管的ViewController,而只是根据它的navigationBarStyle返回. (13认同)
  • 不推荐使用`UIBarStyleBlackTranslucent`,改用`UIBarStyleBlack` (3认同)

And*_*ith 87

好的,这是诀窍.您必须添加"查看基于控制器的状态栏"键并将值设置为否.

这与此键的含义相反,但即使您将值设置为No,您仍然可以更改状态栏的外观,以及它是否在任何视图控制器中显示.因此它的行为类似于"是",但将其设置为"否"!

现在我可以将状态栏设置为白色或黑色.

  • 对我来说这是错的.正如您所料,密钥需要设置为"是".我在Xcode 5.1 iOS 7.1上,所以可能它已经改变了. (6认同)

Dan*_*ood 76

为了preferredStatusBarStyle()在其中工作UINavigationController,UITabBarController我添加以下代码,它将从当前可见的视图控制器获得首选状态栏样式.

extension UITabBarController {
    public override func childViewControllerForStatusBarStyle() -> UIViewController? {
        return selectedViewController
    }
}

extension UINavigationController {
    public override func childViewControllerForStatusBarStyle() -> UIViewController? {
        return visibleViewController
    }
}
Run Code Online (Sandbox Code Playgroud)

对于Swift 3,这些不是方法,而是属性:

extension UITabBarController {
    open override var childViewControllerForStatusBarStyle: UIViewController? {
        return selectedViewController
    }
}

extension UINavigationController {
    open override var childViewControllerForStatusBarStyle: UIViewController? {
        return visibleViewController
    }
}
Run Code Online (Sandbox Code Playgroud)

雨燕4.2的属性已被重命名:

extension UITabBarController {
   open override var childForStatusBarStyle: UIViewController? {
        return selectedViewController
    }
}

extension UINavigationController {
   open override var childForStatusBarStyle: UIViewController? {
        return visibleViewController
    }
}
Run Code Online (Sandbox Code Playgroud)

用法

class ViewController: UIViewController {

    // This will be called every time the ViewController appears
    // Works great for pushing & popping
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }

}
Run Code Online (Sandbox Code Playgroud)

  • 这是迄今为止最好的答案(适用于使用UINavigationController或UITabBarController的应用程序) (6认同)
  • 这是什么用法? (2认同)

Kyl*_*man 34

我可能会迟到一点,但是其他任何人都在寻找一个有效且经过验证的应用程序范围的解决方案.

@mxcl在描述为什么会发生这种情况时是正确的.为了纠正它,我们只需创建一个扩展(或obj-c中的类别),它覆盖UINavigationController的preferredSatusBarStyle()方法.这是Swift中的一个例子:

extension UINavigationController {
    public override func preferredStatusBarStyle() -> UIStatusBarStyle {
        if let rootViewController = self.viewControllers.first {
            return rootViewController.preferredStatusBarStyle()
        }
        return super.preferredStatusBarStyle()
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码只是提取第一个视图控制器(根视图控制器)并解开它(在obj-c中只检查它不是nil).如果unwrap成功(不是nil),那么我们获取rootViewControllers preferredStatusBarStyle.否则我们只返回默认值.

希望这可以帮助任何可能需要它的人.

  • 在Swift 2.0中你必须删除条件语句的"as?UIViewController". (2认同)
  • @Unome`visibleViewController`会更好 (2认同)

Mat*_*ros 21

要在接受的答案中提供更多详细信息,请在app delegate的didFinishLaunchingWithOptions:方法中添加以下行:

[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
Run Code Online (Sandbox Code Playgroud)

然后,在Info.plist中,添加View controller-based status bar appearance并设置为NO.

我相信它应该如何完成,而不是从导航控制器,如果你想要整个应用程序的相同状态栏颜色.您可能拥有不一定嵌入到其他地方UINavigationController的不同UINavigationController子类或其他内容的屏幕.

编辑:你也可以不输入任何代码:https://stackoverflow.com/a/18732865/855680


Use*_*343 10

在viewDidLoad中只写这个

[self setNeedsStatusBarAppearanceUpdate];
Run Code Online (Sandbox Code Playgroud)

只是这样做,它会工作

请你试试这个

Set UIViewControllerBasedStatusBarAppearance to NO.
Call [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
Run Code Online (Sandbox Code Playgroud)

我在你的问题中看到的另一件事是你已经写了这样的方法

 -(void)UIStatusBarStyle PreferredStatusBarStyle ()
        {
            return UIStatusBarStyle.LightContent;
        }
Run Code Online (Sandbox Code Playgroud)

但它应该是这样的

-(UIStatusBarStyle)preferredStatusBarStyle{ 
    return UIStatusBarStyleLightContent; 
} 
Run Code Online (Sandbox Code Playgroud)


And*_*mer 6

即使这里有所有答案,我仍然没有找到适合我的确切解决方案,而是从 Daniel 的答案开始。我最终得到的是:

override var preferredStatusBarStyle: UIStatusBarStyle {
     return visibleViewController?.preferredStatusBarStyle ?? .lightContent
}
Run Code Online (Sandbox Code Playgroud)

在导航控制器中(类似于选项卡,只是 selectedViewController)。然后它将尊重:

override var preferredStatusBarStyle: UIStatusBarStyle {
     return .lightContent
}
Run Code Online (Sandbox Code Playgroud)

在每个视图控制器中,除非你另外设置。我不需要在setNeedsStatusBarAppearanceUpdate()任何地方调用,它只会在您到达每个视图控制器时更新。

  • 在为此挣扎了几个小时后,我最终得到了几乎相同的解决方案。 (2认同)

And*_*rna 6

iOS 13 解决方案

最高投票的答案使用“遗留”代码

设置该barStyle属性现在 (iOS 13+) 被视为“传统自定义”。据苹果称

在 iOS 13 及更高版本中,使用 standardAppearance、compactAppearance 和 scrollEdgeAppearance 属性自定义导航栏。您可以继续使用这些旧访问器直接自定义导航栏的外观,但您必须自己更新不同栏配置的外观。

关于您的尝试 - 您走在正确的轨道上!

UINavigationControllerUIViewController(谁知道)的子类!

因此,当呈现嵌入在导航控制器中的视图控制器时,您并没有真正呈现嵌入的视图控制器;您正在展示导航控制器!UINavigationController,作为 的子类UIViewController,继承preferredStatusBarStylechildForStatusBarStyle,您可以根据需要进行设置。

以下任何一种方法都应该有效:

  1. 覆盖preferredStatusBarStyle范围内UINavigationController

    • preferredStatusBarStyle( doc ) - 视图控制器的首选状态栏样式
    • 子类或扩展 UINavigationController

      class MyNavigationController: UINavigationController {
          override var preferredStatusBarStyle: UIStatusBarStyle {
              .lightContent
          }
      }
      
      Run Code Online (Sandbox Code Playgroud)

      或者

      extension UINavigationController {
          open override var preferredStatusBarStyle: UIStatusBarStyle {
              .lightContent
          }
      }
      
      Run Code Online (Sandbox Code Playgroud)
  2. 覆盖childForStatusBarStyle范围内UINavigationController

    • childForStatusBarStyle( doc ) - 当系统需要使用视图控制器来确定状态栏样式时调用
    • 根据苹果的文档,

      “如果您的容器视图控制器从其子视图控制器之一派生其状态栏样式,[覆盖此属性] 并返回该子视图控制器。如果您返回 nil 或不覆盖此方法,则使用 self 的状态栏样式. 如果此方法的返回值发生更改,请调用 setNeedsStatusBarAppearanceUpdate() 方法。”

    • 换句话说,如果这里不执行方案三,系统就会退回到上面的方案二。
    • 子类或扩展 UINavigationController

      class MyNavigationController: UINavigationController {
          override var childForStatusBarStyle: UIViewController? {
              topViewController
          }
      }
      
      Run Code Online (Sandbox Code Playgroud)

      或者

      extension UINavigationController {    
          open override var childForStatusBarStyle: UIViewController? {
              topViewController
          }
      }
      
      Run Code Online (Sandbox Code Playgroud)
    • 你可以返回任何你喜欢的视图控制器。我推荐以下之一:

      • topViewController(of UINavigationController) ( doc ) - 导航堆栈顶部的视图控制器
      • visibleViewController(of UINavigationController) ( doc ) - 与导航界面中当前可见视图关联的视图控制器(提示:这可以包括“在导航控制器本身之上模态呈现的视图控制器”)

注意:如果您决定子类化UINavigationController,请记住通过 IB 中的身份检查器将该类应用到您的导航控制器。

PS 我的代码使用 Swift 5.1 语法

  • 请注意,执行 override var 的扩展方法在 Xcode 11.4/iOS 13.4 中不再起作用 (2认同)

ary*_*axt 5

这是我如何解决它.通常,navigationController或tabBarController是决定状态栏外观(隐藏,颜色等)的那些.

所以我最终继承了导航控制器并覆盖preferredStatusBarStyle.如果当前可见的ViewContorller实现了StatusBarStyleHandler,我要求将该值用作样式,如果不是,我只返回一个默认值.

触发状态栏外观更新的方法是再次调用setNeedsStatusBarAppearanceUpdate哪个触发器preferredStatusBarStyle并根据方法返回的内容更新UI

public protocol StatusBarStyleHandler {
    var preferredStatusBarStyle: UIStatusBarStyle { get }
}

public class CustomNavigationCotnroller: UINavigationController {

    public override var preferredStatusBarStyle: UIStatusBarStyle {
        if let statusBarHandler = visibleViewController as? StatusBarStyleHandler {
            return statusBarHandler.preferredStatusBarStyle
        }

        return .default
    }
}
Run Code Online (Sandbox Code Playgroud)

然后使用

public class SomeController: UIViewController, StatusBarStyleHandler {

    private var statusBarToggle = true

    // just a sample for toggling the status bar style each time method is called
    private func toggleStatusBarColor() {
        statusBarToggle = !statusBarToggle
        setNeedsStatusBarAppearanceUpdate()
    }

    public override var preferredStatusBarStyle: UIStatusBarStyle {
        return statusBarToggle ? .lightContent : .default
    }
}
Run Code Online (Sandbox Code Playgroud)