79


I tried many ways to set the status bar style (default or lightcontent) but can't get it to work on a per view controller basis. I can set the status bar style for the whole app only.

Does anyone have a hint?

I tried UIViewControllerBasedStatusBarAppearance

and

-(UIStatusBarStyle)preferredStatusBarStyle{ 
    return UIStatusBarStyleLightContent; 
}

but these methods don't work.

Peter DeWeese
  • 18,141
  • 8
  • 79
  • 101
Van Du Tran
  • 6,736
  • 11
  • 45
  • 55
  • http://stackoverflow.com/questions/18979837/cant-hide-ios-7-status-bar/18980833#18980833 – Rajneesh071 Sep 26 '13 at 08:07
  • 1
    And make sure that the navigation bar should not be overlapped with status bar.... – Rajneesh071 Sep 26 '13 at 08:08
  • I used a little trick for it (and for controlling visible/hidden state) – I decided to publish it as pod 'UIViewController+ODStatusBar' (https://cocoapods.org/pods/UIViewController+ODStatusBar) – Alex Nazarov Jun 26 '15 at 10:10
  • 1
    This is just one of dozens of APIs that Apple randomly changes the behaviour of from one version of iOS to the next and for some reason there has not been a complete developer revolt. You'll have to modify your implementation to fit the version of iOS that your app is running on and test it every time you build for a newer version. – Bron Davies Nov 04 '15 at 03:43

10 Answers10

139

Have you tried this?

  1. Set "View controller-based status bar appearance" (UIViewControllerBasedStatusBarAppearance) to YES in your Info.plist. (YES is the default, so you can also just leave this value out of your plist.)

  2. In your viewDidLoad method, call [self setNeedsStatusBarAppearanceUpdate].

  3. Implement preferredStatusBarStyle, returning the status bar style that you want for this view controller.

    - (UIStatusBarStyle) preferredStatusBarStyle { 
        return UIStatusBarStyleLightContent; 
    }
    
Greg
  • 33,450
  • 15
  • 93
  • 100
76

There is a catch here if your view controller is inside standalone UINavigationController and not a part of Storyboard based UINavigationController then above all methods fail. I came across this situation and then in order to set the status bar to light style i used following

[self.navigationController.navigationBar setBarStyle:UIBarStyleBlack];

This worked perfectly for me.

vishal dharankar
  • 7,536
  • 7
  • 57
  • 93
22

EDIT: This solution is deprecated on iOS 9. Please choose one of the other answers.

With UIViewControllerBasedStatusBarAppearance set to NO, I was able to set the style to white text by using:

[UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleBlackTranslucent;

This is because the text color on this style was white on iOS 6 and below.

UPDATE: According to @jowie you can try that on iOS8:

[UIApplication sharedApplication].statusBarStyle = UIBarStyleBlack;
caulitomaz
  • 2,141
  • 14
  • 20
  • did u read the question carefully ? He is asking for iOS7 solution and also its light style not dark which is in your case. – vishal dharankar Feb 02 '14 at 11:32
  • It works on iOS7. I did read it carefully. And about the UIBarStyleBlackTranslucent, it works because this style on iOS6 was black background (translucent) with white text. When you do that on iOS7, it only shows the text in white. I know it looks hackish, but it was the only way I found out to really control the bar. – caulitomaz Feb 17 '14 at 16:37
  • For iOS 8, use `UIBarStyleBlack`. – jowie Jun 04 '15 at 13:57
  • Thanks @MatthieuRiegler, I'll put up a notice. – caulitomaz Sep 28 '15 at 17:39
14

In Swift I was able to do this by writing:

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

moreViewController.navigationBar.barStyle = UIBarStyle.Black

Basically you're interested in the last line.
This resulted in tabbar changing to white:

enter image description here

Note that I didn't change anything in Info.plist in order to achieve this result.
For more informations regarding changing Navigation Status Bar, please check out this link: http://www.appcoda.com/customize-navigation-status-bar-ios-7/

Fengson
  • 4,751
  • 8
  • 37
  • 62
13

On viewDidLoad method, put this:

Objective C

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

Swift

UIApplication.shared.statusBarStyle = .lightContent
self.setNeedsStatusBarAppearanceUpdate()
Zaheer Abbas
  • 225
  • 1
  • 2
  • 10
Jota Freitas Jr
  • 157
  • 1
  • 5
  • I'm glad to help you Gagan – Jota Freitas Jr Apr 15 '15 at 13:56
  • Seems weird that the view controller is updating a property for the entire application - the solution should be either for the entire application (that lives in the `AppDelegate`) or per view controller. – Zorayr Apr 26 '15 at 02:54
  • swift equivalent of this method UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.LightContent, animated: false) – minhazur Jul 27 '16 at 09:08
  • In order for this to work, View Controller Based Status Bar appearance must be set to NO in the target properties. I think this is the best method because it's simple and obvious. – n13 Sep 15 '16 at 18:14
7

I bet you have your view controller embedded into a navigation controller. To avoid setting the navigation bar's style to .Black use this subclass:

class YourNavigationController: UINavigationController {
    override func childViewControllerForStatusBarStyle() -> UIViewController? {
        return topViewController
    }
}
SoftDesigner
  • 5,640
  • 3
  • 58
  • 47
5

Swift:

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

Objective C:

append this to the controller.m file viewDidLoad method:

[self setNeedsStatusBarAppearanceUpdate].

then implement this method in that same controller.m file:

- (UIStatusBarStyle) preferredStatusBarStyle { 
    return UIStatusBarStyleLightContent; 
}

Official docs:

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

Article I wrote on my blog:

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

Darkseal
  • 9,205
  • 8
  • 78
  • 111
1

In the ViewController that you want to change the status bar's color

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

- (void) viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}
jxdwinter
  • 2,339
  • 6
  • 36
  • 56
0

Swift extension for this because I always forget how this works

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()
    }
}
n13
  • 6,843
  • 53
  • 40
0

Xcode 10.3,

In iPhone 8 12.4 Simulator, it is OK.

In iPhone X 12.4 Simulator, I tried all above, not OK.

Then I add it by hand, status bar consists of time, battery, cellular.

11

StatusBarView


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
    }

}


dengApro
  • 3,848
  • 2
  • 27
  • 41