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


79


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

有人暗示吗?

我试过了 UIViewControllerBasedStatusBarAppearance

-(UIStatusBarStyle)preferredStatusBarStyle{ 
    return UIStatusBarStyleLightContent; 
}

但是这些方法不起作用。



1
并确保导航栏不应与状态栏重叠....
Rajneesh071

我为此使用了一些技巧(并用于控制可见/隐藏状态)–我决定将其发布为pod'UIViewController + ODStatusBar'(cocoapods.org/pods/UIViewController+ODStatusBar
Alex Nazarsky

1
这只是Apple随机将数十种API的行为从一个版本的iOS更改为另一个版本的API之一,由于某种原因,尚未完全引起开发人员的反感。您必须修改实现以适合您的应用运行的iOS版本,并在每次构建新版本时对其进行测试。
布朗·戴维斯

Answers:


139

你有尝试过吗?

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

  2. 在您的viewDidLoad方法中,调用[self setNeedsStatusBarAppearanceUpdate]

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

    - (UIStatusBarStyle) preferredStatusBarStyle { 
        return UIStatusBarStyleLightContent; 
    }
    

我不需要第一步
Van Du Tran 2013年

2
此设计适用于Iphone 5 + ios7。UIViewControllerBasedStatusBarAppearance为否,[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackTranslucent]; 在我的案子上运作良好:)
Femina 2014年

4
如果您将代码放入自定义的UINavigationController子类中,则@vishal可以与基于UINavigationController的应用程序一起使用
anneblue 2014年

3
您不需要第二步。
pronebird 2014年

4
在iOS 8中不适用于我。这只是更改了默认设置。我需要设置为白色,现在变为默认设置。
noobsmcgoobs 2015年

74

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

[self.navigationController.navigationBar setBarStyle:UIBarStyleBlack];

这对我来说非常有效。


7
如果导航控制器的导航栏处于隐藏状态,则不起作用。
MLQ

类似的建议适用于UISplitViewController。我结束了子类化。
斯蒂芬·达林顿

1
根据我的理解,UINavigationBar.barStyle覆盖preferredStatusBarStyle。无论如何设置preferredStatusBarStyle,一个该死的`UINavigationBar.setBarStyle'都会接管一切。
Desmond DAI

22

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

随着UIViewControllerBasedStatusBarAppearance设置为NO,我能够通过设置样式为白色文字:

[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleBlackTranslucent;

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

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

[UIApplication sharedApplication].statusBarStyle = UIBarStyleBlack;

你仔细阅读了这个问题吗?他正在要求iOS7解决方案,以及您想要的不浅的浅色样式。
vishal dharankar 2014年

它适用于iOS7。我确实仔细阅读了。关于UIBarStyleBlackTranslucent,它之所以起作用,是因为iOS6上的这种样式是黑色背景(半透明)和白色文本。在iOS7上执行此操作时,它仅以白色显示文本。我知道它看起来有点黑,但这是我发现真正控制酒吧的唯一方法。
caulitomaz

对于iOS 8,请使用UIBarStyleBlack
jowie 2015年

谢谢@MatthieuRiegler,我会发出通知。
caulitomaz

14

在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”,我想知道这是否是一个可以证明未来的解决方案?仍然解决问题!
Van Du Tran 2015年

1
本来可以是一个很好的答案,但是如果您的导航栏处于隐藏状态,则无法使用。
MLQ

13

在viewDidLoad方法上,输入以下内容:

目标C

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

迅速

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

我很高兴为您提供帮助Gagan
Jota Freitas Jr

似乎很奇怪,视图控制器正在更新整个应用程序的属性-解决方案应该是针对整个应用程序(驻留在中AppDelegate)或每个视图控制器。
Zorayr

此方法的快速等效UIApplication.sharedApplication()。setStatusBarStyle(UIStatusBarStyle.LightContent,animation:false)
minhazur

为了使它起作用,必须在目标属性中将基于View Controller的状态栏外观设置为NO。我认为这是最好的方法,因为它简单明了。
n13

7

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

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

5

迅速:

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/


1

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

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

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

0

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()
    }
}

0

Xcode 10.3,

在iPhone 8 12.4 Simulator中,可以。

在iPhone X 12.4 Simulator中,我尝试了以上所有方法,但不行。

然后,我手动添加它,状态栏包括时间,电池,手机。

11

状态栏视图


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
    }

}

BatteryLevelView

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
    }

}


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.