I have 3 view controllers which are added to a pageViewController so I can scroll between the 3. The issue is I want to display the status bar in only 1 of the viewControllers. So far I can hide from them all or show in them all.
I tried the following:
private var isStatusBarHidden = false {
didSet {
setNeedsStatusBarAppearanceUpdate()
}
}
override var prefersStatusBarHidden: Bool {
return isStatusBarHidden
}
How I added the VC's as child view controllers to my scroll view:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
page1 = storyboard.instantiateViewController(withIdentifier: StoryboardIdentifiers.feedViewController.rawValue) as! FeedViewController
page1.view.translatesAutoresizingMaskIntoConstraints = false
page1.delegate = self
scrollView.addSubview(page1.view)
addChildViewController(page1)
page1.didMove(toParentViewController: self)
You have 3 VC means all 3 ViewController is going to have viewDidAppear and viewWillDisappear code
override open func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
//It will show the status bar again after dismiss
UIApplication.shared.isStatusBarHidden = true
}
override open func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
//It will hide the status bar again after dismiss
UIApplication.shared.isStatusBarHidden = false
}
override open var prefersStatusBarHidden: Bool {
return true
}
Copy and paste code into those ViewController in which you want to hide your status bar.
So what it will do is inside your viewDidAppear it will hide your status bar
and as soon as we will leave the class it will set status bar visible.
In case your pageViewController is parent view then We can do it via page index
Let suppose you want to show status bar on page 2 and hide on page 1 and 3.
So we can do it, in this page
PageDataSource Function {
if(index == 1 || index == 3){
UIApplication.shared.isStatusBarHidden = true
}
else{
UIApplication.shared.isStatusBarHidden = false
}
}
override open var prefersStatusBarHidden: Bool {
return true
}
override open func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
//It will hide the status bar again after dismiss
UIApplication.shared.isStatusBarHidden = false
}
Please try this and let me know if its working or not
Thank you
Related
I use Xcode 11.2 and the project minimum iOS deployment target is iOS 12.4.
I have a TabBarController on root page and on one of the tabs I have FirstViewController. When I push SecondViewController from FirstViewController, I want the tab bar to be hidden. I used hidesBottomBarWhenPushed property to hide the tab bar.
The tab bar is hidden when I push SecondViewController but when I pop the SecondViewController and move back to FirstViewController, the tab bar is still hidden.
I tried several ways to set hidesBottomBarWhenPushed to false when moving back to FirstViewController but none of the tries worked.
How can I re display tab bar when popped back to FirstViewController?
class FirstViewController: UIViewController {
#IBAction func buttonTap(_ sender: Any) {
let vc2 = SecondViewController()
// Set to Hide TabBar
hidesBottomBarWhenPushed = true
navigationController?.pushViewController(vc2, animated: true)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// This Does Not Work
hidesBottomBarWhenPushed = false
}
}
class SecondViewController: UIViewController {
/*
All The Followings Does Not Work
*/
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
hidesBottomBarWhenPushed = false
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
hidesBottomBarWhenPushed = false
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
hidesBottomBarWhenPushed = false
}
}
The key was to set hidesBottomBarWhenPushed to true from outside of the SecondViewController.
The code below was all I needed to write.
class FirstViewController {
func pushSecondViewController {
let vc = SecondViewController()
vc.hidesBottomBarWhenPushed = true // <- Here
navigationController?.push
navigationController?.pushViewController(vc, animated: true)
}
}
I have one View Controller and this View Controller contains two views/scenes in the main.storybard.
I am trying to hide the top navigation bar at first view/scene, but unhide it again on the second view/scene.
I tried with
self.navigationController?.isNavigationBarHidden = true
But this will only work with two View Controller classes.
Does anyone have a idea to manage it?
Hide navigationbar in viewWillAppear & unhide in viewWillDisappear
var shouldHideNavBar = false
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(shouldHideNavBar, animated: animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if shouldHideNavBar == true {
navigationController?.setNavigationBarHidden(false, animated: animated)
}
}
And when you perform segue set shouldHideNavBar as true
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "show") {
let viewController = segue!.destinationViewController as! ViewController
viewController.shouldHideNavBar = true
}
}
You should use extra control. Or you can create an IBInspactable variable and assing it's value on Interface Builder. Like this:
#IBDesignable class myViewController: UIViewController{
#IBInspectable var isNavbarHidden: Bool = true{
didSet{
self.navigationController?.isNavigationBarHidden = isNavBarHidden
}
}
override func viewDidLoad(){
super.viewDidLoad()
//I am not sure if this line is necessary
self.navigationController?.isNavigationBarHidden = isNavBarHidden
}
}
After then go to InterfaceBuilder(your storyboard file) and set its value for your Scenes on your viewControllers properties.
I have a UITabBarController. One of the tabs contains a UINavigationController.
I'd like to push a view controller onto the navigation stack and hide the tab bar on that view controller. I can do this easily with:
toVC.tabBarController?.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(toVC, animated: true)
or doing it in the storyboard:
The problem is, this hides the tab bar for any subsequent view controllers I push onto the stack. I'd like to simply hide the tab bar for this one view controller and show it for all other view controllers before and after it.
There is a workaround. It works the way it is presented on gif below.
For each UIViewController that is pushed into the UINavigationController stack I override the hidesBottomBarWhenPushed property this way:
override var hidesBottomBarWhenPushed: Bool {
get {
switch navigationController?.topViewController {
case .some(let controller):
switch controller == self {
case true:
return super.hidesBottomBarWhenPushed
case false:
return false
}
default:
return super.hidesBottomBarWhenPushed
}
}
set {
super.hidesBottomBarWhenPushed = newValue
}
}
The first switch checks whether this controller belongs to some UINavigationController stack. The second switch checks whether current top UIViewController of UINavigationController stack is self.
Hope it will work in your case. Happy coding (^
If you hide on the storyboard then by this property your tab bar will hide for all the view controllers. So you can manage this by code.
You can do this programmatically by just writing one line of code in ViewDidLoad() or ViewWillAppear() method
For Swift 3:-
self.tabBarController?.tabBar.isHidden = true
And where you want to unhide the tab bar just write the following code in ViewDidLoad () or ViewWillAppear() method
self.tabBarController?.tabBar.isHidden = false
Try this in the view controller you want to hide the tab bar in:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.tabBar.isHidden = true
}
And this in the view controllers before and after the one you want to hide the tab bar in:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.tabBar.isHidden = false
}
EDIT:
Fully implemented example:
class ViewController1: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.tabBar.isHidden = false
}
}
class ViewController2: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.tabBar.isHidden = true
}
}
class ViewController3: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.tabBar.isHidden = false
}
}
In my rootViewController i have hidden status bar. When i tried to push the new viewcontroller and pop back, then navigation bar is pushed up and there is the gap between navigation bar and content view. Here are the screenshot of navigation bars.
Here is the code in rootViewController
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.statusBarHidden = true
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
private var statusBarHidden = true {
didSet {
self.setNeedsStatusBarAppearanceUpdate()
}
}
override var prefersStatusBarHidden: Bool {
get {
return statusBarHidden
}
}
I resolved this issue by adding the following line to -viewDidLoad:
extendedLayoutIncludesOpaqueBars = true
try to hide the status bar from a modal view.
already check several methods:
override func prefersStatusBarHidden() -> Bool {
return true
}
with / without self.setNeedsStatusBarAppearanceUpdate()
also
UIApplication.sharedApplication().setStatusBarHidden(true, withAnimation: .Fade)
but depreciated in iOS 9
this works in fullscreen presentation (modal segue presentation option) but note in over full screen which is my setting.
if you have any idea..
For a non-fullscreen presentation of a View Controller, you need to use the modalPresentationCapturesStatusBarAppearance property.
e.g.
toViewController.modalTransitionStyle = .coverVertical
toViewController.modalPresentationStyle = .overFullScreen
toViewController.modalPresentationCapturesStatusBarAppearance = true
fromViewController.present(toViewController,
animated: true,
completion: nil)
For a fullscreen presentation of a View Controller, you need to:
set the new VC's modalPresentationStyle.
override prefersStatusBarHidden in the new VC
set your app plist UIViewControllerBasedStatusBarAppearance value to YES
e.g.
toViewController.modalTransitionStyle = .coverVertical
toViewController.modalPresentationStyle = .fullScreen
fromViewController.present(toViewController,
animated: true,
completion: nil)
(Yes, status bar setting in iOS is pitifully bad. It's no wonder Stack Overflow has so many questions on the subject, and so many varied answers.)
To hide the status bar when doing an over full screen modal, you need to set this in viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
modalPresentationCapturesStatusBarAppearance = true
}
Then do the standard method to hide status bar:
override var prefersStatusBarHidden: Bool {
return true
}
Indeed for FullScreen status bar update called automatically, but not for OverFullScreen.
Furthermore in my case i was need to deal with navigation controller in stack, to pass ModalViewController as child:
extension UINavigationController {
public override func childViewControllerForStatusBarHidden() -> UIViewController? {
return self.visibleViewController
}
public override func childViewControllerForStatusBarStyle() -> UIViewController? {
return self.visibleViewController
}
}
Inside ModalViewController we manually update status bar, also in order to make it smooth we have to do that in viewWillDisappear, but at that point visibleViewController still ModalViewController, nothing left as to use internal bool statusBarHidden and update it accordingly
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.statusBarHidden = true
self.setNeedsStatusBarAppearanceUpdate()
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.statusBarHidden = false
self.setNeedsStatusBarAppearanceUpdate()
}
override func prefersStatusBarHidden() -> Bool {
return self.statusBarHidden
}
If you are using a storyboard and you want to hide/show the status bar, you can use this method on previous view controller:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
UIApplication.shared.setStatusBarHidden(false, with: UIStatusBarAnimation.none)
}