iOS 7 及更高版本:为每个视图控制器设置状态栏样式

Posted

技术标签:

【中文标题】iOS 7 及更高版本:为每个视图控制器设置状态栏样式【英文标题】:iOS 7 and later: set status bar style per view controller 【发布时间】:2013-10-01 13:54:40 【问题描述】:

我尝试了许多方法来设置状态栏样式(默认或 lightcontent),但无法让它在每个视图控制器的基础上工作。我只能为整个应用设置状态栏样式。

有人有提示吗?

我试过UIViewControllerBasedStatusBarAppearance

-(UIStatusBarStyle)preferredStatusBarStyle 
    return UIStatusBarStyleLightContent; 

但这些方法不起作用。

【问题讨论】:

***.com/questions/18979837/cant-hide-ios-7-status-bar/… 并确保导航栏不与状态栏重叠...... 我使用了一个小技巧(以及控制可见/隐藏状态)——我决定将其发布为 pod 'UIViewController+ODStatusBar' (cocoapods.org/pods/UIViewController+ODStatusBar) 这只是 Apple 随机将 iOS 版本的行为更改为下一个版本的几十个 API 之一,并且由于某种原因,开发人员还没有完全反抗。您必须修改您的实现以适应您的应用运行的 iOS 版本,并在每次构建新版本时对其进行测试。 【参考方案1】:

你试过了吗?

    在 Info.plist 中将“基于控制器的状态栏外观”(UIViewControllerBasedStatusBarAppearance) 设置为 YES。 (YES 是默认值,因此您也可以将此值保留在 plist 之外。)

    在你的 viewDidLoad 方法中,调用[self setNeedsStatusBarAppearanceUpdate]

    实现preferredStatusBarStyle,返回此视图控制器所需的状态栏样式。

    - (UIStatusBarStyle) preferredStatusBarStyle  
        return UIStatusBarStyleLightContent; 
    
    

【讨论】:

我不需要第 1 步 这项功能适用于 Iphone 5 + ios7。 UIViewControllerBasedStatusBarAppearance 为 NO 并且 [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent];我的情况很好:) @vishal 与基于 UINavigationController 的应用程序一起使用,如果您将该代码放入自定义 UINavigationController 子类中 您不需要第二步。 在 iOS 8 中对我不起作用。这只是更改了默认值。我需要的是白色的,现在使用默认设置。【参考方案2】:

如果您的视图控制器位于独立的 UINavigationController 内部而不是基于 Storyboard 的 UINavigationController 的一部分,那么这里有一个问题,那么所有方法都会失败。我遇到了这种情况,然后为了将状态栏设置为浅色,我使用了以下

[self.navigationController.navigationBar setBarStyle:UIBarStyleBlack];

这对我来说非常有效。

【讨论】:

如果您的导航控制器的导航栏被隐藏,则不起作用。 类似的建议适用于 UISplitViewController。我最终进行了子类化。 据我了解,UINavigationBar.barStyle 会覆盖preferredStatusBarStyle。不管你如何设置preferredStatusBarStyle,一个该死的 `UINavigationBar.setBarStyle' 会接管一切。【参考方案3】:

编辑:此解决方案在 iOS 9 上已弃用。请选择其他答案之一。

UIViewControllerBasedStatusBarAppearance 设置为 NO,我可以使用以下方法将样式设置为白色文本:

[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleBlackTranslucent;

这是因为这种样式的文字颜色在 iOS 6 及更低版本上是白色的。

更新:根据@jowie,您可以在 iOS8 上尝试:

[UIApplication sharedApplication].statusBarStyle = UIBarStyleBlack;

【讨论】:

你仔细阅读问题了吗?他要求 iOS7 解决方案以及它的浅色风格,而不是你的情况。 它适用于iOS7。我确实仔细阅读了它。关于 UIBarStyleBlackTranslucent,它之所以有效,是因为 iOS6 上的这种样式是黑色背景(半透明)和白色文本。当您在 iOS7 上执行此操作时,它只会以白色显示文本。我知道它看起来很老套,但这是我发现真正控制酒吧的唯一方法。 对于 iOS 8,请使用 UIBarStyleBlack 谢谢@MatthieuRiegler,我会发通知的。【参考方案4】:

在 Swift 中,我可以通过以下方式做到这一点:

let tbc : UITabBarController = self.window?.rootViewController as UITabBarController
var moreViewController : UINavigationController = tbc.moreNavigationController

moreViewController.navigationBar.barStyle = UIBarStyle.Black

基本上你对最后一行感兴趣。 这导致标签栏变为白色:

请注意,我没有更改 Info.plist 中的任何内容以实现此结果。 有关更改Navigation Status Bar 的更多信息,请查看此链接: http://www.appcoda.com/customize-navigation-status-bar-ios-7/

【讨论】:

这行得通。但是,它没有使用新的“UIStatusBarStyleLightContent”,我想知道它是否是面向未来的解决方案?还是解决问题! 会是一个很好的答案,但如果您的导航栏被隐藏,则不起作用。【参考方案5】:

在 viewDidLoad 方法上,这样写:

目标 C

[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
[self setNeedsStatusBarAppearanceUpdate];

斯威夫特

UIApplication.shared.statusBarStyle = .lightContent
self.setNeedsStatusBarAppearanceUpdate()

【讨论】:

我很高兴能帮助你,加根 视图控制器正在更新整个应用程序的属性似乎很奇怪 - 解决方案应该针对整个应用程序(位于 AppDelegate 中)或每个视图控制器。 这个方法的swift等效 UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.LightContent, animated: false) 为了使其工作,必须在目标属性中将基于视图控制器的状态栏外观设置为 NO。我认为这是最好的方法,因为它简单明了。【参考方案6】:

我敢打赌,您的视图控制器已嵌入到导航控制器中。为避免将导航栏的样式设置为.Black,请使用以下子类:

class YourNavigationController: UINavigationController 
    override func childViewControllerForStatusBarStyle() -> UIViewController? 
        return topViewController
    

【讨论】:

【参考方案7】:

斯威夫特:

let tbc : UITabBarController = self.window?.rootViewController as UITabBarController
var moreViewController : UINavigationController = tbc.moreNavigationController
moreViewController.navigationBar.barStyle = UIBarStyle.Black

目标 C:

将此附加到 controller.m 文件 viewDidLoad 方法:

[self setNeedsStatusBarAppearanceUpdate].

然后在同一个controller.m 文件中实现此方法:

- (UIStatusBarStyle) preferredStatusBarStyle  
    return UIStatusBarStyleLightContent; 

官方文档:

https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/TransitionGuide/Bars.html

我在博客上写的文章:

http://www.ryadel.com/2015/03/04/xcode-set-status-bar-style-and-color-in-objective-c/

【讨论】:

【参考方案8】:

在要更改状态栏颜色的 ViewController 中

- (void) viewWillAppear:(BOOL)animated
    [super viewWillAppear:animated];
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];


- (void) viewWillDisappear:(BOOL)animated
    [super viewWillDisappear:animated];
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];

【讨论】:

【参考方案9】:

Swift 扩展,因为我总是忘记它是如何工作的

extension UIViewController 
    // utility to set the status bar appearance
    // Note: Make sure "View controller-based status bar appearance" is set to NO in your target settings or this won't work
    func setStatusBarForDarkBackground(dark: Bool) 
        UIApplication.sharedApplication().statusBarStyle = dark ? .LightContent : .Default
        setNeedsStatusBarAppearanceUpdate()
    

【讨论】:

【参考方案10】:

Xcode 10.3,

在 iPhone 8 12.4 Simulator 中是可以的。

在 iPhone X 12.4 Simulator 上,我都试过了,不行。

然后我手动添加,状态栏由时间、电池、蜂窝组成。

状态栏视图


class StatusBottomView: UIView 
    private var batteryView:BatteryView!
    private var timeLabel:UILabel!
    private var timer:Timer?

    override init(frame: CGRect) 
        super.init(frame: frame)
        addSubviews()
    

    private func addSubviews() 
        batteryView = BatteryView()
        batteryView.tintColor = UIColor.blue
        addSubview(batteryView)
        timeLabel = UILabel()
        timeLabel.textAlignment = .center
        timeLabel.font = UIFont.systemFont(ofSize: 12)
        timeLabel.textColor = UIColor.blue
        addSubview(timeLabel)
        didChangeTime()
        addTimer()
    

    override func layoutSubviews() 
        super.layoutSubviews()
        let h = frame.size.height
        let x: CGFloat = 80
        batteryView.frame.origin = CGPoint(x: ScreenHeight - x - DZMBatterySize.width, y: (h - DZMBatterySize.height) / 2)
        timeLabel.frame = CGRect(x: x, y: 0, width: 50, height: h)
    

    // MARK: -- Timer

    func addTimer() 
        if timer == nil 
            timer = Timer.scheduledTimer(timeInterval: 15, target: self, selector: #selector(didChangeTime), userInfo: nil, repeats: true)
            RunLoop.current.add(timer!, forMode: .common)
        
    


    func removeTimer() 
        if timer != nil 
            timer!.invalidate()
            timer = nil
        
    


    @objc func didChangeTime() 
        timeLabel.text = TimerString("HH:mm")
        batteryView.batteryLevel = UIDevice.current.batteryLevel
    



电池电量查看

class BatteryView: UIImageView 

    override var tintColor: UIColor! 

        didSet batteryLevelView.backgroundColor = tintColor 
    

    /// BatteryLevel
    var batteryLevel:Float = 0 

        didSet setNeedsLayout() 
    

    /// BatteryLevelView
    private var batteryLevelView:UIView!

    convenience init() 

        self.init(frame: CGRect(x: 0, y: 0, width: DZMBatterySize.width, height: DZMBatterySize.height))
    


    override init(frame: CGRect) 

        super.init(frame: CGRect(x: 0, y: 0, width: DZMBatterySize.width, height: DZMBatterySize.height))

        addSubviews()
    

    func addSubviews() 

        batteryLevelView = UIView()
        batteryLevelView.layer.masksToBounds = true
        addSubview(batteryLevelView)

        image = UIImage(named: "battery_black")?.withRenderingMode(.alwaysTemplate)
        tintColor = UIColor.white
    

    override func layoutSubviews() 
        super.layoutSubviews()

        let spaceW:CGFloat = 1 * (frame.width / DZMBatterySize.width) * HJBatteryLevelViewScale
        let spaceH:CGFloat = 1 * (frame.height / DZMBatterySize.height) * HJBatteryLevelViewScale

        let batteryLevelViewY:CGFloat = 2.1*spaceH
        let batteryLevelViewX:CGFloat = 1.4*spaceW
        let batteryLevelViewH:CGFloat = frame.height - 3.4*spaceH
        let batteryLevelViewW:CGFloat = frame.width * HJBatteryLevelViewScale
        let batteryLevelViewWScale:CGFloat = batteryLevelViewW / 100

        var tempBatteryLevel = batteryLevel

        if batteryLevel < 0 

            tempBatteryLevel = 0

        else if batteryLevel > 1 

            tempBatteryLevel = 1

        

        batteryLevelView.frame = CGRect(x: batteryLevelViewX , y: batteryLevelViewY, width: CGFloat(tempBatteryLevel * 100) * batteryLevelViewWScale, height: batteryLevelViewH)
        batteryLevelView.layer.cornerRadius = batteryLevelViewH * 0.125
    




【讨论】:

以上是关于iOS 7 及更高版本:为每个视图控制器设置状态栏样式的主要内容,如果未能解决你的问题,请参考以下文章

用户登录后更新根视图控制器 + iOS 13 及更高版本

iOS 7 中的视图移动到导航栏上方,但在 iOS 6 中可以正常工作

iOS 在 iPhone 6 及更高版本上设置导航项标题视图框架故障

我应该怎么做才能使这个菜单栏在 Internet Explorer 7 及更高版本中正常工作?

iOS 7 和 iOS 8 中的警报视图与 UIAlertController

如何在 iOS 7 中隐藏状态栏?