Background: I implemented a Custom UIViewController Transition where the first view controller (VC1) has a visible status bar
override func prefersStatusBarHidden() -> Bool {
return false
}
while the second presented view controller (VC2) has a hidden status bar:
override func prefersStatusBarHidden() -> Bool {
return true
}
Transitioning is controlled by the user since I implemented a pull to open transition with gesture controllers.
Objective: I want the status bar to be hidden during appearance transition AND disappearance transition (essentially like the Google Maps Slide Out Menu).
Problem: The status bar is correctly hidden during the entire appearance transition of ViewController VC2. But during the entire disappearance transition the status bar is visible. Any suggestions on how to properly implement this for iOS 9?
Just try to set status bar hidden on viewWillAppear and viewWillDisappear function.
You can create an instance var to hold the status bar hidden state and return this boolean from prefersStatusBarHidden(). When this value changes, call setNeedsStatusBarAppearanceUpdate().
For example:
var statusBarHidden = true {
didSet {
if oldValue != statusBarHidden {
setNeedsStatusBarAppearanceUpdate()
}
}
}
override var prefersStatusBarHidden: Bool {
return statusBarHidden
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
statusBarHidden = false
}
Related
I've got a generic UIViewController in which I would like to hide the status bar. I've got more view controllers which should display the status bar, but this specific view controller should hide the status bar.
I've implemented the following methods in the UIViewController class:
override func viewDidLoad() {
super.viewDidLoad()
// FIXME: hide status bar
var prefersStatusBarHidden: Bool {
return true
}
setNeedsStatusBarAppearanceUpdate()
}
override func viewWillAppear(_ animated: Bool) {
UIApplication.shared.isStatusBarHidden = true
}
override func viewWillDisappear(_ animated: Bool) {
UIApplication.shared.isStatusBarHidden = false
}
In my info.plist, I've set up the following setting:
The status bar does not hide when I navigate to that view controller and is still visible.
override prefersStatusBarHidden in your view controller:
override var prefersStatusBarHidden: Bool {
return true
}
Set a value No for View Controller based status bar appearance and then show/hide your status bar for specific view controller.
Here is result:
In view controller where you want to hide the status bar,
In the viewWillAppear method, UIApplication.shared.isStatusBarHidden = true,
In the viewWillDisAppear method, UIApplication.shared.isStatusBarHidden = false
To turn off the status bar for some view controllers but not all, remove this info.plist entry if it exists OR set it to YES:
View controller-based status bar appearance = YES
Then add this line to each view controller that needs the status bar hidden
override var prefersStatusBarHidden: Bool { return true }
To turn off the status bar for the entire application, add this to info.plist:
View controller-based status bar appearance = NO
This will allow the "Hide status bar" to work as expected. Check the hide status bar located in the project's General settings under Deployment Info.
UIApplication.shared.isStatusBarHidden = true
above this Setter for 'isStatusBarHidden' was deprecated in iOS 9.0
so use below code it's working fine :)
override var prefersStatusBarHidden: Bool {
return true
}
App Delegate
swift 4.2
NotificationCenter.default.addObserver(self, selector: #selector(videoExitFullScreen), name:NSNotification.Name(rawValue: "UIWindowDidBecomeHiddenNotification") , object: nil)
#objc func videoExitFullScreen() {
UIApplication.shared.setStatusBarHidden(false, with: .none)
}
In Swift 5
override var preferredStatusBarStyle: UIStatusBarStyle {
return .default
}
Add following line in your ViewController
extension UIViewController {
func prefersStatusBarHidden() -> Bool {
return true
}
}
I have two ViewControllers, using a custom segue from the first I present the second, with custom animator and a percent based interactor.
I want to slide up the status bar alongside the controller transition.
In the second ViewController I have this in order to hide the status bar
override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
return .slide
}
override var prefersStatusBarHidden: Bool {
return true
}
I know I should call setNeedsStatusBarAppearanceUpdate() in an animation block in order to animate it, and use UIViewControllerTransitionCoordinator method animateAlongsideTransition: in order to make it follow the transition, but I am not sure where should I call this method.
I tried in the viewWillAppear method of the second controller but it still disappeared immediately without animation.
What is the right place to call this?
The reason why you couldn't see the animation is because in your second view controller you always return true to prefersStatusBarHidden, then such view controller starts with that condition, hence doesn't have any "chance" for playing the animation.
So in the second view controller you might try doing so:
class ViewController2: UIViewController {
override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation { get { return .slide } }
override var prefersStatusBarHidden: Bool { return statusBarHidden }
var statusBarHidden = false
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.statusBarHidden = true
UIView.animate(withDuration: 0.35) {
self.setNeedsStatusBarAppearanceUpdate()
}
}
}
Moreover in your Info.plist be sure to have View controller-based status bar appearance= YES
I have a view controller A that shows the status bar on top. From that view controller I want to present another view controller B that hides the status bar. In order to achieve that I override the property
override var prefersStatusBarHidden: Bool {
return true
}
on B. For enforcing a smooth animation whenever the status bar (dis)appears I also override the property
override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
return .slide
}
However, when I now present view controller B from A the status bar disappears abruptly while A is still visible, right before the animated modal transition begins.
I'm searching for a way to fix this "jumping status bar" behavior. Ideally, I would like to have a clean separation:
A: shows status bar
B: does not show status bar
so that, when I present B, the status bar is covered by it.
As the status bar seems to be a global view that doesn't belong to any particular view controller it's probably difficult to achieve that kind of behavior. So in case it's not possible to replicate this exact animation behavior, I'd also be happy if the status bar slides out smoothly during the view controller transition. How can I achieve that?
For animating the status bar during the transition, you could do something like this in view controller B:
var willAppear = false
override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
return .slide
}
override var prefersStatusBarHidden: Bool {
return willAppear
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
willAppear = true
UIView.animate(withDuration: 0.5) {
self.setNeedsStatusBarAppearanceUpdate()
}
}
Then I guess you would need to do the opposite if you want the reverse effect when the modal controller is dismissed.
You can adjust the duration of the animation to whatever suits you, though I'm not sure how consistent the duration between viewWillAppear and the modal controller actually being fully presented will be.
EDIT:
"Opposite" ends up being something like this (in view controller A):
var willAppear = false
override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
return .slide
}
override var prefersStatusBarHidden: Bool {
return willAppear
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let _ = presentedViewController as? B {
willAppear = true
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
if let _ = presentedViewController as? B {
willAppear = false
UIView.animate(withDuration: 0.5) {
self.setNeedsStatusBarAppearanceUpdate()
}
}
}
Which I agree, is way too much code for something that I imagine many people want.
I wonder if its OK by iOS Human Interface Guidelines to style a UIView so it looks and acts like a navbar.
My problem is that I want to hide my current navbar once the user scrolls.
I have tried both self.navigationController?.setNavigationBarHidden(true, animated: true) and navigationController?.hidesBarsOnSwipe = true but the animation looks odd, once the navigation bar gets hidden I still have about 20px space under the status bar: You can look at my other question
So to make things easier, can I just init my view tih the navbar hidden and style my own and add the proper animation?
Try this out :
extension YourViewController {
override func prefersStatusBarHidden() -> Bool {
return barsHidden // Custom property
}
override func preferredStatusBarUpdateAnimation() -> UIStatusBarAnimation {
return .Slide
}
}
You have to update barsHidden somewhere in the code and call setNeedsStatusBarAppearanceUpdate() method.
I'm trying to hide my Status Bar and Navigation bar when the view is tapped. Currently I found something that works from a previous question, but the problem is that there is no animation when hiding the bars. It just disappears.
Here is my current code in my View Controller:
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.hidesBarsOnTap = true
}
override func prefersStatusBarHidden() -> Bool {
if self.navigationController?.navigationBarHidden == true {
return true
}
else
{
return false
}
}
When I tap again, the animation works when the two bars are coming back on to the screen.
If I don't include the overrided prefersStatusBarHidden function, I can get the navigation bar to hide with the desired sliding animation. But the status bar is still there.
Any suggestions? Does Swift 2 have a new method that can work?
Try this
var statusBarHidden = false
func tapAction() {
self.navigationController?.navigationBarHidden = true
self.statusBarHidden = true
self.setNeedsStatusBarAppearanceUpdate()
}
override func prefersStatusBarHidden() -> Bool {
return statusBarHidden
}
Have you set View controller-based status bar appearance = NO in the info.plist?