LulzCow
LulzCow

Reputation: 1229

Hide UIStatusBar without removing the space allocated for it

I have picture examples to show you what I want and what I have right now.

First, here is an example of what I'm trying to do, from the Slack app:

The statusbar is normally displayed:

enter image description here

But when you open the side drawer, it goes away:

enter image description here

I can display the status bar in my app:

enter image description here

But when I hide it, it also hides the frame, so there is less space at the top than before:

enter image description here

It looks wonky to remove space from the top whenever the side drawer opens, but it also looks bad to not hide the status bar since the menu has a different background color. How can I hide the text on the status bar while keeping the space for it still there?

Upvotes: 4

Views: 1595

Answers (4)

Roger Lee
Roger Lee

Reputation: 330

I've encounter status bar shrink when create a slack style sidebar view on iPhone 8(which has no notch), the best way to keep top spacing is to set additionalSafeAreaInsets.top = 20, 20pt is a constant of status bar height.

Demo Image: https://i.sstatic.net/MmeXw.gif

Demo

func hasNotch() -> Bool {
    return self.view.safeAreaInsets.bottom > 20
}

if show {
    UIView.animate(withDuration: 0.5, delay: 0,usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseOut, animations: {
        self.centerView.view.frame.origin.x = self.centerView.view.frame.width - self.menuWidth
        self.menuView.view.frame.origin.x = 0
        
        // IMPORTANT: The code below fix status bar shrink when device has no notch.
        if !self.hasNotch() {
            self.additionalSafeAreaInsets.top = 20
        }
    }, completion: nil)
} else {
    UIView.animate(withDuration: 0.5, delay: 0,usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseOut, animations: {
        self.centerView.view.frame.origin.x = 0
        self.menuView.view.frame.origin.x = -self.menuWidth
        
        // IMPORTANT: The code below fix status bar shrink when device has no notch.
        if !self.hasNotch() {
            self.additionalSafeAreaInsets.top = 0
        }
    }, completion: nil)
}

Upvotes: 1

thieumao
thieumao

Reputation: 9

I did succeed with this solution.

extension UIApplication {
    var statusBarView: UIView? {
        if responds(to: Selector("statusBar")) {
            return value(forKey: "statusBar") as? UIView
        }
        return nil
    }

    func hideStatusBar() {
        statusBarView?.frame.origin.y = -200
        statusBarView?.isHidden = true
    }

    func showStatusBar() {
        statusBarView?.frame.origin.y = 0
        statusBarView?.isHidden = false
    }
}

Upvotes: 1

Frankie
Frankie

Reputation: 11928

I couldn't get the accepted answer to work on iOS 10 in Swift 3. So here is what I came up with:

class ViewController: UIViewController {

    override var prefersStatusBarHidden: Bool {
        return true
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        UIView.animate(withDuration: 0.3, animations: {
            let bounds = self.navigationController!.navigationBar.bounds
            self.navigationController?.navigationBar.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height + 20)
        })
    }
}

Upvotes: 1

daredevil1234
daredevil1234

Reputation: 1425

I think you want something like the following (In Swift, Deploy target is 9.0):

To hide it:

    UIApplication.sharedApplication().setStatusBarHidden(true, withAnimation: .Fade)
    let appFrame:CGRect = UIScreen.mainScreen().applicationFrame

    UIView.animateWithDuration(0.3, animations: {
        self.navigationController?.navigationBar.frame = self.navigationController!.navigationBar.bounds
        self.view.window!.frame = CGRectMake(0, 0, appFrame.size.width, appFrame.size.height);
    })

To show it again:

    let appFrame:CGRect = UIScreen.mainScreen().applicationFrame
    UIApplication.sharedApplication().setStatusBarHidden(false, withAnimation: .Fade)

    UIView.animateWithDuration(0.3, animations: {
        self.navigationController?.navigationBar.frame = self.navigationController!.navigationBar.bounds
        self.view.window!.frame = CGRectMake(0, 0, appFrame.size.width, appFrame.size.height-0.00001);
    })

I'm not sure you will run into the same issue as I will, but when I tested the code I originally didn't have that "-0.00001" and the transition was not smooth but that little subtraction fixed it. Not sure why.

Upvotes: 2

Related Questions