I have a UITabBar
in my app, which I\'m hiding on the first UIViewController
in the first tab by putting this line in the AppDelegate
This is an issue that has bugged me for a while, and I only just found a solution that works. The hidesBottomBarWhenPushed
property is a very strange beast, and works in, to my mind, a counter-intuitive way.
The problem with it is that when you push a new view controller (or pop back) the navigationController will ask all view controllers (from top to bottom) if they want to hide the bottom bar, and if any of them say YES
the tabbar will be hidden, which is why the tabbar remains hidden despite setting NO
to hiding on the new view controller.
Here is my solution - override the hidesBottomBarWhenPushed
getter in the view controller that you wish to not have a tabbar, and check if it is at the top of the stack:
Objective-C
- (BOOL) hidesBottomBarWhenPushed
{
return (self.navigationController.topViewController == self);
}
Swift (not so obvious, hence snippet)
override var hidesBottomBarWhenPushed: Bool {
get {
return navigationController?.topViewController == self
}
set {
super.hidesBottomBarWhenPushed = newValue
}
}
This nicely encapsulates the hide/show logic in one place, so you dont have to think about it outside of the viewcontroller that does the hiding.
Not sure if a solution was found for this but I just managed to get this working.
My scenario:
I have a UITabBarController
with 4 tab bar items.
On one of the tab bar items it loads a UIViewController
with buttons on it. The buttons calls a IBOutlet
function that loads another UIViewController
which contains the a tab bar at the bottom.
After many trial & error........
On the IBOutlet
function, I do the following:
{
self.hidesBottomBarWhenPushed = YES;
/* Push the new controller with tab bar */
}
This was working fine with the UITabBarController's
tab bar sliding to the left and my tab bar from the pushed controller sliding from the right.
Obviously from functionality perspective I need to push the initial UITabBarController's
tar bar back in when "going back".
After many trial & error........
I have the method viewWillDisappear
in the UIViewController
that pushes the UIViewController
with tab bar as:
- (void) viewWillDisappear:(BOOL)animated
{
self.hidesBottomBarWhenPushed = NO;
}
I ran a few quick tests on this in the simulator and it seems to work fine.
Some contributors suggests that this is bad UI but I am trying this out at the moment to see how it works out.
Happy to receive (cop) any feedbacks. :)
I had the same issue, but after 3 hours I was found solution! In this topic answered Oct 8 '10, Dave Batton said:
Right way to use hidesBottomBarWhenPushed property is:
self.anotherViewController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:self.anotherViewController animated:animated];
I think you misunderstood the hidesBottomBarWhenPushed use. If YES, the bottom bar remains hidden until the view controller is popped from the stack.
So if I understand your question correctly:
The secondViewController should be the YES, the firstViewController should be the NO.
I figured out a really easy to way to solve this by subclassing UINavigationController
. You could accomplish the same thing by using a category with an associated object but I already had a subclass so I just threw the code in there.
First, you add an ivar to your UINavigationController:
@interface CustomNavigationController ()
{
NSMutableSet *_viewControllersWithHiddenBottomBar;
}
@end
Then I overrode the push and pop methods to take over handling the hiding logic:
- (void) pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if(viewController.hidesBottomBarWhenPushed)
{
viewController.hidesBottomBarWhenPushed = NO;
[_viewControllersWithHiddenBottomBar addObject:viewController];
[self rootViewController].hidesBottomBarWhenPushed = YES;
}
else
{
[self rootViewController].hidesBottomBarWhenPushed = NO;
}
[super pushViewController:viewController animated:animated];
}
- (UIViewController *) popViewControllerAnimated:(BOOL)animated
{
if([_viewControllersWithHiddenBottomBar containsObject:self.viewControllers[self.viewControllers.count - 2]])
{
[self rootViewController].hidesBottomBarWhenPushed = YES;
}
else
{
[self rootViewController].hidesBottomBarWhenPushed = NO;
}
UIViewController *poppedViewController = [super popViewControllerAnimated:animated];
[_viewControllersWithHiddenBottomBar removeObject:poppedViewController];
return poppedViewController;
}
- (UIViewController *) rootViewController
{
return ((UIViewController *)self.viewControllers.firstObject);
}
I use the hidesButtomBarWhenPushed
property to populate the set and then reset the value at the viewcontroller level (since if any view controller has this property set, everything on top of it will also have it hidden). To make things simple I use the root viewcontroller to control showing and hiding the tabbar based on the values in the set.
You also need to initialize the set somewhere, I just used initWithRootViewController:
.
This works pretty seamlessly for me and is the least hacky way I could think of to do this, without taking over any existing animations and having to handle edge cases.
Set View controller in
I have no need setting screen in tabbar, this setting screen in past two methods and setting screen to push any screen in display bottom Tabbar.
override func viewWillAppear(_ animated: Bool) {
self.hidesBottomBarWhenPushed = true
}
override func viewDidAppear(_ animated: Bool) {
self.hidesBottomBarWhenPushed = false
}
Thanks, if you have any query free to ask.