I cannot seem to be able to hide the status bar in my root view controller (A) when a button is pressed.
I have set the properties in my info.plist Status bar is initially hidden and View controller-based status bar appearance to YES.
If I implement the override var prefersStatusBarHidden: Bool { get }, the status bar will be definitively hidden (or not).
What I need
I want the status bar to be displayed in (A) but hidden when I press a button that adds a child view controller to (A).
I have tried setting prefersStatusBarHidden to false and hide it using UIApplication.shared.isStatusBarHidden = true when the button is pressed but this does not work.
There must be something I am getting wrong, could anyone enlighten me ?
Thanks in advance.
PS: I merely need it to be invisible, not necessarily "hidden" in the Swift sense.
To hide the status bar
UIApplication.shared.keyWindow?.windowLevel = UIWindowLevelStatusBar
To bring back the status bar
UIApplication.shared.keyWindow?.windowLevel = UIWindowLevelNormal
You can create a variable to hold a boolean to set if the status bar is hidden or not
var _isStatusBarHidden: Bool = false
Then create its getter and setter
var isStatusBarHidden: Bool {
get{
return _isStatusBarHidden
}
set {
if _isStatusBarHidden != newValue {
_isStatusBarHidden = newValue
self.setNeedsStatusBarAppearanceUpdate()
}
}
}
You must override the prefersStatusBarHidden property
override var prefersStatusBarHidden: Bool {
return self._isStatusBarHidden
}
Last thing is to set the variable to true when the user presses the button:
self.isStatusBarHidden = true
Just a little improvement of #Alexandre Lara `s code:
var isStatusBarHidden: Bool = false {
didSet {
if oldValue != self.isStatusBarHidden {
self.setNeedsStatusBarAppearanceUpdate()
}
}
}
override var prefersStatusBarHidden: Bool {
return self.isStatusBarHidden
}
Related
I have a view controller that takes up the whole screen from top to bottom. I would like to hide the home bar indicator on the bottom of the screen on iPhone X devices.
How can I do this in iOS 11?
You should override prefersHomeIndicatorAutoHidden in your view controller to achieve that:
override var prefersHomeIndicatorAutoHidden: Bool {
return true
}
There is another alternative. If you are looking for the behavior where the indicator dims, then when the user swipes up it activates, and when they swipe up again the home action is invoked (I.E., two swipes are needed to invoke), then the answer is here: iPhone X home indicator behavior. The short of it is to override on your UIViewController:
override var preferredScreenEdgesDeferringSystemGestures: UIRectEdge {
return UIRectEdge.bottom
}
prefersHomeIndicatorAutoHidden only hides the indicator, but will not suppress the gesture.
And you will get what you want (If I understand your comments correctly - your question and the selected answer seem to imply the other answer).
If your window?.rootViewController is a UITabBarController or UINavigationController, just inherit it and add two function as follows,
override var prefersHomeIndicatorAutoHidden: Bool {
return true
}
//#available(iOS 11, *)
override var childViewControllerForHomeIndicatorAutoHidden: UIViewController? {
return nil
}
Implement -(BOOL)prefersHomeIndicatorAutoHidden in your UIViewController and return YES.
Read more https://developer.apple.com/documentation/uikit/uiviewcontroller/2887510-prefershomeindicatorautohidden.
I tried to set it and return true only when I am in full-screen :
override var prefersHomeIndicatorAutoHidden: Bool { isNavigationBarAndTabBarHidden }
but it doesn't seem to work... isNavigationBarAndTabBarHidden is a custom variable tied to my fullscreen extension.
Edit: We need to call setNeedsUpdateOfHomeIndicatorAutoHidden every time we update prefersHomeIndicatorAutoHidden's value.
var isNavigationBarAndTabBarHidden = false {
didSet {
setNeedsUpdateOfHomeIndicatorAutoHidden()
}
}
override func prefersHomeIndicatorAutoHidden() -> Bool {
return true
}
I suppose you can add this method in your AppDelegate for hide home indicator on all of your ViewControllers.
How to hide, show or change the status bar dynamically on events such as click or value change?
I've googled for a well, but all I get is changed from the beginning as this. Here I need to do it dynamically.
Well for this you can do following based on events:
//For hiding/unhiding:
func hideStatusBar(shouldHide:Bool){
UIApplication.shared.isStatusBarHidden = shouldHide
}
//For Light Style:
func lightStatusBar(){
UIApplication.shared.statusBarStyle = .lightContent
}
//For Standard Style:
func standardStatusBar(){
UIApplication.shared.statusBarStyle = .default
}
or you can tweak prefersStatusBarHidden: as well.
UIApplication.sharedApplication().setStatusBarHidden=true
You are looking for var prefersStatusBarHidden: Bool { get }
Override that function in your view controller. Dynamically update the visibility of your statusbar with func setNeedsStatusBarAppearanceUpdate()
https://developer.apple.com/reference/uikit/uiviewcontroller/1621440-prefersstatusbarhidden
I have prefersStatusBarHidden dynamic return value, it does show/hide the statusbar, Except of one problem:
When prefersStatusBarHidden return value is false, the statusbar is shown no matter if we are on a vertically compact environment (which is not the default behaviour when not using prefersStatusBarHidden).
Is there any way to use prefersStatusBarHidden still be able to detect if we are on vertically compact environment and hide the statusbar.
My current code looks something like below:
class SomeViewController: UIViewController {
var someStatusValue = false
override var prefersStatusBarHidden : Bool {
guard (someStatusValue) else { return true }
// Here instead of returning `false`, if we are on VERTICALLY COMPACT ENVIRONMENT return `true` else `false`
return false
}
}
Additional: I am using UINavigationController based viewcontroller, and View controller-based status bar appearance: YES in info.plist
I just finally figured it out
override var prefersStatusBarHidden : Bool {
guard (someStatusValue) else { return true }
if (UIDevice.current.userInterfaceIdiom == .phone && UIDeviceOrientationIsLandscape(UIDevice.current.orientation)) {
return true
} else {
return false
}
}
I also have following line to register for orientation change in viewWillAppear
NotificationCenter.default.addObserver(self, selector: #selector(orientationChanged(_:)), name: .UIDeviceOrientationDidChange, object: nil)
And the function which is responsible for recieving the notification and updating the statusbar:
func orientationChanged(_ note: Notification) {
self.setNeedsStatusBarAppearanceUpdate()
}
Note: you must NotificationCenter.default.removeObserver to unregister for orientation notifications in viewWillDisappear
I have a scroll view with 2 views in it: a UIImagePicker (Snapchat-style camera view), and a UITableView.
The scroll view is inside of a navigation controller that the main viewController pushes to. I want the status bar and everything on it (time, battery, wifi, etc.) to be hidden on the camera view, but when you scroll to the right to the tableView, the status bar contents show back up, whether they do some kind of cool stretch animation as you scroll (would be awesome to figure that out) or any other solution possible.
Hopefully I worded this well enough for you to understand.
Solution I found (More of a workaround)
declare a boolean called hidden.
Then I overrode these methods:
func scrollViewDidScroll(scrollView: UIScrollView){
let xOffset = scrollView.contentOffset.x;
if(xOffset > scrollView.contentSize.width/4)
{
if hidden == true {
print("\nShow status bar\n")
hidden = false
UIView.animateWithDuration(0.3, animations: {
self.setNeedsStatusBarAppearanceUpdate()
})
}
} else
{
print("\nHide Status Bar\n")
hidden = true
UIView.animateWithDuration(0.2, animations: {
self.setNeedsStatusBarAppearanceUpdate()
})
}
}
override func preferredStatusBarUpdateAnimation() -> UIStatusBarAnimation {
if hidden == false {
return UIStatusBarAnimation.Fade
} else {
return UIStatusBarAnimation.Slide
}
}
override func prefersStatusBarHidden() -> Bool {
print("\nstatus Bar Changed to hidden = \(hidden)\n")
return hidden
}
It fades the status bar in once you've at least scrolled half way, and slides the status bar back up once you've gone back half way again.
Have you tried calling
UIApplication.sharedApplication().setStatusBarHidden(hidden: Bool, withAnimation: UIStatusBarAnimation)
In appropriate timing (which is not recommended because you'll have to set it back to what it was when leaving the view, just so you know)
Or the override method
override func prefersStatusBarHidden() -> Bool {
code
}
in your controller?
I got two buttons, show and hide button and I want to hide the status bar when the button hide is clicked I tried this method but it didn't work
- (IBAction)hide:(id)sender {
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:
UIStatusBarAnimationSlide];
}
Is there is any way to do what I want?
you can simply set it's delegate :-
- (BOOL)prefersStatusBarHidden
{
return YES;
}
and called this method in to your method [self setNeedsStatusBarAppearanceUpdate];
In your app's plist file add a row call it "View controller-based status bar appearance" and set it to NO.
For Swift 3 and iOS10
This is how I'm using it with AVPlayer (not part of a question but on click is the same) with fullscreen support
private var fullscreenEnabled: Bool = false
func videoFullscreenButtonClicked(_ sender: UIButton!) {
if avPlayerLayer.videoGravity == AVLayerVideoGravityResizeAspectFill {
avPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspect
fullscreenEnabled = false
setNeedsStatusBarAppearanceUpdate()
} else {
avPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
fullscreenEnabled = true
setNeedsStatusBarAppearanceUpdate()
}
}
override var prefersStatusBarHidden: Bool {
return fullscreenEnabled
}