I am having multiple view controller in my application. I want to hide navigationbar in my first view controller. So I use the following code to hide the navigation bar
navigationController?.setNavigationBarHidden(navigationController?.navigationBarHidden == false, animated: true);
Now I want to add navigation bar in some other viewController but, my navigation bar not visible in that viewcontroller. Why it is happening?
My storyboard showing the navigation bar but once I try to run my application it is gone.
If I hide navigation bar from one view controller then we can't use navigation controller, Is it so? I hope I am wrong. Then what are the reasons for navigation bar not shown?
EDIT:
Also I want my view controller in portrait mode only. So I did the following Is that causing the issue?
extension UINavigationController{
public override func shouldAutorotate() -> Bool {
if (UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeLeft ||
UIDevice.currentDevice().orientation == UIDeviceOrientation.LandscapeRight ||
UIDevice.currentDevice().orientation == UIDeviceOrientation.Unknown) {
return false
}
else {
return true
}
}
public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return [UIInterfaceOrientationMask.Portrait ,UIInterfaceOrientationMask.PortraitUpsideDown]
}
}
Edit 1:
I am using following code to move from one view controller not link from the storyboard. Is that causing issue now?
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let secondViewController = storyboard.instantiateViewControllerWithIdentifier("HomeVC")
presentViewController(secondViewController, animated: false, completion: nil)
Edit 2:
Please check my following screenshots. Which are my settings for secondview controller
Edit 3:
Here is my navigation controller attribute inspector
Navigation Controller is a controller, which has stack of view controllers. So if you have something like this:
NAV -> A -> (segue) B
Even if you'll hide navigation bar you still should be able to make segues. Also can't you just unhide navigation bar in second (B) view controller in viewWillAppear? And in first the same way hide it on viewWillAppear.
edit: Final solution to the problem:
Use:
let controller = storyboard.instantiateViewControllerWithIdentifier("HomeVC")
self.navigationController!.pushViewController(controller)
instead of:
let secondViewController = storyboard.instantiateViewControllerWithIdentifier("HomeVC")
presentViewController(secondViewController, animated: false, completion: nil)
Because pushViewController will add secondViewController to its stack. presentViewController was replacing your navigation controller that's why you couldn't see navigation bar.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Hide the navigation bar on the this view controller
self.navigationController?.setNavigationBarHidden(true, animated: animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Show the navigation bar on other view controllers
self.navigationController?.setNavigationBarHidden(false, animated: animated)
}
in viewDidLoad method of the view controller in which you don't want to show navigation bar add the line
navigationController.navigationBarHidden = true
you are presently hiding in all view controllers
Edit: You are presenting view controller instead it should be
self.navigationController!.pushViewController(controller)
do like in viewcontroller based hidden using Swift 4.0
To hide navigationController in viewWillAppear
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = true
}
To unhide navigationController in viewWillDisappear
override func viewWillDisappear(animated: Bool)
{
super.viewWillDisappear(animated)
self.navigationController?.isNavigationBarHidden = false
}
I am having same requirement in my swift project.
this is how I have handled Navigation bar
Make sure your first screen is embedded into Navigation controller
example we have two screens A and B
In screen A you need to hide navigation bar in viewWillAppear
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
//hide navigation for screen A
self.navigationController?.navigationBarHidden = true
}
for enabling Navigation in screen B
you need to add below code in screen A
override func prepareForSegue(segue: (UIStoryboardSegue!), sender: AnyObject!)
{
if (segue.identifier == "screen B's segue identifier here")
{
//enable navigation for screen B
navigationController?.setNavigationBarHidden(navigationController?.navigationBarHidden == false, animated: true)
}
}
Using above style, I can enable or disable navigation bar for specific screen, whenever I want
If you need to have this navigation bar hidden only in this controller, the best way is to show it in viewWillDisappear() and hide in viewWillAppear().
It's too late to reply and there are other good answers but I would like to share what worked for me.
let controller = self.storyboard?.instantiateViewControllerWithIdentifier("HomeVC")
self.navigationController!.pushViewController(controller!, animated:true)
Related
I have a tab bar which I only need on five screens. However, it goes to every screen when I push the view controller. How do I stop this from happening. I found a lot of solutions telling me to use hidesBottomBarWhenPushed but the problem I'm having with that is when I pop the view controller the tab bar is gone. How do I solve this problem? Also, please give me suggestions on my questions as I'm sort of new here! Thanks!
Edit: I've also seen this: self.tabBarController?.tabBar.hidden = false, but this kind of looks odd as the tab bar just disappears in the middle of the push animation.
Need to inherit UINavigationController custom navigation controller, override pushViewController & setViewControllers method to set hidesBottomBarWhenPushed, and then use custom navigation controller to jump
open class CustomNavigationController: UINavigationController {
...
open override func pushViewController(_ viewController: UIViewController, animated: Bool) {
if viewControllers.count > 0 {
viewController.hidesBottomBarWhenPushed = true
}
super.pushViewController(viewController, animated: animated)
}
open override func setViewControllers(_ viewControllers: [UIViewController], animated: Bool) {
if viewControllers.count > 1, let vc = viewControllers.last {
vc.hidesBottomBarWhenPushed = true
}
super.setViewControllers(viewControllers, animated: animated)
}
}
I actually figured it out. Basically in your viewdidAppear you add in self.hidesBottomBarWhenPushed = true and in your viewDidDisappear you add in
self.hidesBottomBarWhenPushed = false. Thanks for your guys's answers anyways.
I have several view controllers and they are very complexed.
MainVC (embed with tab bar controller)
FriendListVC
ChatRoomUpperVC (embed with navigation view controller)
ChatRoomVC (NavigationViewController with embed in ChatRoomUpperVC) (only shows the tab bar)
ChatRoomQuestionVC (pushed from ChatRoomVC) (only shows the navigation bar)
MatchedWaitVC (pushed from ChatRoomQuestionVC) (hide both tab and navigation bars)
ChatVC (pushed from MatchedWaitVC) (only shows the navigation bar)
SettingVC
What I have to do is when I click the back button from the ChatVC, I should back to ChatRoomVC and show the tab bar on the bottom only.
I tried the code below but it shows the black screen and there is no tar bar neither.
override func willMove(toParentViewController parent: UIViewController?) {
if parent == nil
{
var viewControllers = navigationController?.viewControllers
viewControllers?.removeLast(3)
navigationController?.setViewControllers(viewControllers!, animated: true)
self.navigationController?.isNavigationBarHidden = true
self.tabBarController?.tabBar.isHidden = false
}
}
I guess you can use following hack to achieve what you want. In the viewDidLoad method of the ChatVC do:
override func viewDidLoad() {
super.viewDidLoad()
if let root = navigationController?.viewControllers.first {
navigationController?.viewControllers = [root, self]
}
}
This will remove the inbetween view controllers that are between ChatVC and ChatRoomVC. Now popping back (e.g. using the standard back button, or swiping from the left edge of the screen) will jump back directly to the ChatRoomVC.
EDIT
To show the tabBar again in the ChatRoomVC, add this to the viewDidAppear:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.tabBarController?.tabBar.isHidden = false
}
This will ensure that as soon as ChatRoomVC appears on the screen, its tabBar will be presented, too.
I want one of my pushed viewControllers in a navigation controller stack to be "full screen" - no navigation bar and no status bar.
I have this code that hides and shows the navigation bar in one of the view controllers of navigation controller (I want it to be pushed on full screen):
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated:animated)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.setNavigationBarHidden(false, animated:animated)
}
In the same viewController I'm also hiding the status bar with this:
override var prefersStatusBarHidden: Bool {
return true
}
It is hiding and showing as expected but the problem is that I get a black stripe on the transition when pushing this view controller and back from it (see images).
Push to this controller:
Push to this controller
And back from this controller (back button):
Back from this controller
It appears this is happening because of the prefersStatusBarHidden function Removing this solves the issue.
The code for show/hide the nav bar is taken from:
https://stackoverflow.com/a/2406167/4207465
and based on apple developer library:
"Showing and Hiding the Navigation Bar -
When a navigation bar is used in conjunction with a navigation controller, you always use the setNavigationBarHidden:animated: method of UINavigationController to show and hide the navigation bar..."
Not sure why it's happening,
Thanks for the help!
#Boaz Frenkel
There is one solution to fix the black strip during hide and show of navigation bar with or without status bar.
ViewController A : Fullscreen View
override func viewWillAppear(animated: Bool) {
self.navigationController?.setNavigationBarHidden(true, animated: animated)
super.viewWillAppear(animated)
}
override func viewDidAppear(animated: Bool) {
UIApplication.sharedApplication().setStatusBarHidden(true, withAnimation: .Fade)
super.viewDidAppear(animated)
}
ViewController B : With NavigationBar and status bar
override func viewWillAppear(animated: Bool) {
self.navigationController?.setNavigationBarHidden(false, animated: animated)
UIApplication.sharedApplication().setStatusBarHidden(false, withAnimation: .None)
super.viewWillAppear(animated)
}
Please try to hide navigation bar in viewDidAppear. Now you're hidding bar before showing controller.
func viewDidAppear(_ animated: Bool) {
super. viewDidAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: animated)
}
I have following View Controller hierarchy in my storyboard.
When I perform show segue from tab 1 of Groups Tab bar Controller by selecting the tableview cell, the Lists tab bar is presented but it have Groups's tab bar instead of its own tab bar.
How can I make it to show it's own tab bar when Lists's Controller is shown. Thanks
PS: I have one more tab bar controller in the hierarchy.
Make sure you set the Storyboard ID in interface builder for "List Tab Bar Controller." (Example below tabBar2)
Give a name for the segue between the TableViewController and ListTabBarController. (Example below show1)
Add the following code to prepare (for segue):
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "show1" {
let _ = navigationController?.popViewController(animated: true)
let storyborad = UIStoryboard(name: "Main", bundle: nil)
let tabVC2 = storyborad.instantiateViewController(withIdentifier: "tabBar2") as! UITabBarController
self.present(tabVC2, animated: true, completion: nil)
}
}
Adding this code
override func viewWillAppear(_ animated: Bool) {
self.hidesBottomBarWhenPushed = true
}
override func viewWillDisappear(_ animated: Bool) {
self.hidesBottomBarWhenPushed = false
}
in Table View Controller of both Tab bar Controllers worked. Now every Tab bar Controller's View Controllers have their own tab bar.
In my TabBarController, I'm presenting a UINavigationController as a modal. Once I present it, I'd like everything to be transparent (including the navigation bar). However, I'd like everything after the root controller to be opaque.
let transVC = self.storyboard?.instantiateViewControllerWithIdentifier("TransparentViewController") as! TransparentViewController
transVC.delegate = self
transVC.view.backgroundColor = UIColor.clearColor()
transVC.modalPresentationStyle = .CurrentContext
self.navController = UINavigationController(rootViewController: transVC)
self.navController?.modalPresentationStyle = .CurrentContext
self.presentViewController(self.navController!, animated: false, completion: nil)
Later, I will push other view controllers onto the stack. I want them to be opaque.
let messageVC = self.storyboard?.instantiateViewControllerWithIdentifier("MessagesViewController") as! MessagesViewController
self.navController!.pushViewController(messageVC, animated: false) //should be opaque
If there is no sure way to do this, maybe we can take a screenshot of the app and set it as the background, as a workaround? How would I do that?
No, taking a screenshot is not necessary for a modally presented view controller to have a transparent background. Just present the segue using the presentation style of .OverFullScreen or .OverCurrentContext, rather than .CurrentContext, and ensure the view controller has a clear colored background.
Also, make sure you are setting the modalPresentation style of the navigation controller since that is what you are presenting, and therefore what will be used by the modal segue:
navController?.modalPresentationStyle = .OverFullScreen
Auto-(un)hiding Navigation Bar
For the navigation bar to be hidden on the navigation controller's root view controller, I would subclass the root view controller so that when it appears, the navigation bar is hidden. When it disappears, the navigation bar should be unhidden.
In TransVC:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: true)
}
Because it can be animated, setNavigationBarHidden integrates seamlessly with pushViewController. Alternatively, you could move the line that unhides the navigation bar to the viewWillAppear method in the view controller you are presenting.