Here's my situation :
I have a UINavigationController
inside a UITabBarController
. When I drill down the navigation controller, at some point I have to hide the UITabBar
because I want the view to have as much space as possible.
I do that by using self.hidesBottomBarWhenPushed = YES
inside the pushed UIViewController
, and it works quite well.
However, I want to show the UITabBar
back in the following pushed controllers. I've tried to put self.hidesBottomBarWhenPushed = NO
in the other controllers, but the UITabBar won't come back.
It seems to be normal as the documentation states :
hidesBottomBarWhenPushed
If YES, the bar at the bottom of the screen is hidden; otherwise, NO. If YES, the bottom bar remains hidden until the view controller is popped from the stack.
And indeed, when the controller with this property set to yes is popped, the tabbar does come back.
Is there any proper way to show the UITabBar
when a controller is pushed, once it's been hidden?
Thanks in advance
Okay, here have we an awfully long way to go.
As you read from the document, the default behavior is clear: once a view controller's
hides...
property is YES, the tab bar is hidden until the view controller is popped. What you want directly contradicts this, and for various reasons, I would first recommend not to take this approach.However, it doesn't mean it is impossible to implement.
hides...
property back to NOYou cannot modify the default behavior. To show the tab bar, all view controllers in the stack must set their
hides...
property to NO. So from the view where the tab bar is hidden, if you want to show the bar again when a new view is pushed, you have to set the previous view controller'shides...
property back toNO
again.Just before you push a new view controller, set the property back to NO.
By doing this, you will have the tab bar again. However, you will recognize the tab bar is pushed in from the left, while the new view is pushed from the right. This is clearly not desirable, so we need to fix this.
The thing is, the default layer action (the animation) used when the tab bar appears again, is a push transition animation from the left. UITabBar implements
- (id < CAAction >)actionForLayer:(CALayer *)layer forKey:(NSString *)key
method that tells to use the animation from the left for the case. We need to override this method, to return an animation from the right instead.To show the tab bar back, Cocoa modifies its layer's
position
property. Therefore, our new method should return an animation from the right for the keyposition
, and for all the other keys, it should use the default implementation. Note that usingposition
for the tab bar is not documented by Apple, so it's subject to change without a notice in the following versions. We are implementing something directly contradicts Apple's specification anyway, so can't complain much.However, you cannot just use subclassing to override the method. Because even if you have a custom subclass of UITabBar, you cannot modify UITabBarController class to use it instead of the default UITabBar.
So, it gets a bit more complex. In order to implant your own logic to UITabBar class, you have to 'swap' the implementation for the message
actionForLayer: forKey:
.First, add a new method to UITabBar class using category.
And in the
viewDidAppear
method of the tab bar controller, insert the following codes.You want to do this in
viewDidAppear
rather thanviewDidLoad
, because otherwise the tab bar will slide in from the right in the first time the application shows up.Now when a UITabBar instance gets a message
actionsForLayer forKey:
, the custom methodcustomActionForLayer forKey:
is invoked. It intercepts the keyposition
, and returns an animation from the right. If it's for another key, it invokes the original implementation of the message, which is now connected to the messagedefaultActionsForLayer forKey:
.Okay, there we are. Remember when popping back the views, you may have to set the
hides...
property back to YES, because you set it to NO when pushing a new view (and do some similar tricks to animate it properly).I've spent some time on this but ironically, I have to say *Do not use this again, because it uses an undocumented information of Cocoa classes ("position" key for tab bar animation), contradicts the documented behaviors, and is against Apple's human interface guideline. You may find out that your application wouldn't work the same with the following SDK versions, that the users cannot easily adopt the interface, or even that Apple rejects your application on App store.
Then what on earth is my answer for? Well, an example of some interesting topics on the iOS development, I guess (and a proof showing that I'm terribly unproductive today :P).