hideBottomBarOnPush not working on child views - ios

Pushing using segues with parameter on performSegues will hide the bottom bar when hidesBottomBarOnPush is set to true, the problem is on the child view of the view that has been hidden you cannot show/unhide the bottom bar. Already tried hidesBottomBarOnPush = false. Is there any way to unhide the bottom bar when the parent view's bottom bar is hidden.
Edit:
If I use the tabBar.hidden a small white rect will be shown at the bottom of the view. And also another problem with that is, when I change to another tab then go back to the tab I'm working on, the child view is retained but tabBar becomes hidden.
Legend:
3rd view controller - is the parent view that push segues.
4th view controller - is the child view.
Hoping someone can help me with this problem.

if you want to hide the bottom bar in one particular view controller,and show in others, try this, i think this works better than hidesBottomBarOnPush
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self.tabBarViewController.tabBar setHidden:YES];
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear];
[self.tabBarViewController.tabBar setHidden:NO];
}

Related

Popping UIViewController causes previous UIViewControllers View to change position

I have a UINavigationController with a UIViewController set as it's rootController, it contains a background on its UIView using an image set just under the navBar. I then push onto the navigation controller a new UIViewController and when the back button is pushed, the previous controller looks different. Using the visual debugger I can see that the self.view has moved entirely down below the navBar where previously it was at the top. I have no idea and been racking my brains as to why this might be happening
-(void)pushIPhoneMessagingContactsController:(MessageContactsViewController *)contactsController{
self.selectorView.hidden = YES;
[self.navigationController pushViewController:contactsController animated:YES];
}
On the RootViewController (iPhoneMessagingNotificationsController)
-(void)viewWillAppear:(BOOL)animated{
self.selectorView.hidden = NO;
[[[self navigationItem] leftBarButtonItem] setTintColor:[UIColor blackColor]];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault];
if ([_displayType intValue] == MESSAGES_SHOWING) {
[self.notificationsViewController.view removeFromSuperview];
[self.contentView addSubview:_messagesViewController.view];
} else {
[self.messagesViewController.view removeFromSuperview];
[self.contentView addSubview:_notificationsViewController.view];
}
}
It seems the offending line was in the viewWillAppear method of the pushed UIViewController
self.navigationController.navigationBar.translucent = YES;
Somewhere else this navigationBar gets set as translucent:
[self.navigationController.navigationBar setBackgroundImage:[UIImage new]
forBarMetrics:UIBarMetricsDefault];
self.navigationController.navigationBar.shadowImage = [UIImage new];
self.navigationController.navigationBar.translucent = YES;
and to make it solid colour again:
self.navigationController.navigationBar.shadowImage = nil;
self.navigationController.navigationBar.translucent = NO;
but this code seems to mess with the layout so perhaps there is another way to change the opacity of the navBar and statusBar without affecting the layout?
What you're currently trying to do is hide or show a selectorView which really only should appear for one specific view controller.
Here's an encapsulated way to solve this that makes your selectorView a part of the root view controller, removing the connection from other view controllers. They no longer have to know about it or hide it.
Add your selectorView to your rootViewController's navigation bar titleView. (You can do this in code, or drop it in Storyboard and add an IBOutlet for it.)
self.navigationItem.titleView = selectorView;
Now when you push another view controller, its title will replace your rootViewController's selectorView title (view). Your other view controllers don't need to know anything about that view.
This is a good design approach in general. Anytime you have a control that should only appear on one view controller's navigation bar, you want to make it a part of that view controller's navigationItem (titleView, or left/right bar button items.) iOS will display the control when it presents that view controller, and hide the control when that view controller is no longer the top view controller in the navigation controller stack.
As for the 64-pixel height issue, it's likely related to some complexity in the rootViewController hierarchy that shouldn't be there.
In iOS 7/8, a view's content, by default, appears under a translucent navigation bar. Apple freely managed this for you, by insetting the first view of the view hierarchy.
From your code, it appears that you're trying to "hide" or "show" the (un)selected viewController's view.
Each view controller should have a view it controls. A view controller shouldn't be trying to control other view controller's views, or adding other view controller's views to its own view hierarchy.
Here's Apple's recommended way to approach this. Use a containerView in your rootViewController. The whole purpose of a container view is to encapsulate a view controller within a view. As your selectorView changes which view to show, you have your container view transition from one view controller to the other. (If you're not familiar with how to do that, check out this answer.)
Pin the containerView to the rootViewController's view, so Auto Layout can size it for you.
Your view hierarchy now looks like view -> containerView, instead of view -> hidden view of unselected view controller, shown view of selected view controller. Apple can adjust the first view's inset, and nothing gets incorrectly offset (by the height of the navigation control).
Update:
This question talks about scrollViewInsets and how they can be set on a view-controller-by-view-controller basis. If you do have a view controller, and you don't want its content to appear under a bar, uncheck that box.
But the best way to handle this is to "standardize" your UI, so it isn't varying from view to view. Either make the bar always be translucent, or not always be translucent. This makes transitions less "jarring" for the users.

Auto Layout and "Hide bottom bar when pushed"

My app's (simplified) structure is this:
UITabBarController with one UINavigationController holding a UITableViewController as root view controller.
when tapping one of the table view controller cells, I push a regular UIViewController (lets call it VC) end hiding the bottom tab bar. (using the "Hide bottom bar when pushed" flag)
In storyboard I added a regular UIView subclass to VC that look like a bottom bar, and I use Auto Layout to pin it to the bottom of the VC view.
The problem
when I push VC it takes a second for this view to pin to the bottom, it looks like auto layout pin it to the bottom as if the tab bar is not hidden and after a sec it recognise that the tab bar is hidden and moves it to the real bottom of the view.
I know its not the best explanation, so I added a very simple project to demonstrate the issue.
The problem is with this specific constraint which is between the view and the top of the bottom layout guide.
Select the constraint and edit its "Second Item" property
Here you need to choose bottom
Once you have that, the pink view is not influenced by layout guide anymore. The layout guide seem to acknowledge that the tab bar is hidden only after the root view of the pushed view controller is in the bounds of main screen and this happens only when the animation is finished.
And that is the reason the view hierarchy needs to be laid out again which causes the unwanted animation.
The accepted answer did not work for me (the option was not available). However I have found another solution. (based on Hide Bottom Bar When Pushed through Autolayout)
Select booth the view and the object to align (in my case btnShare) and add a new alignment constraint (Bottom Edges).
Hi In storyboard select Tab bar (Is Tab Bar Controller Scene > Tab Bar Controller > Tab Bar ), in the attribute inspector, uncheck Translucent box. This action fix your problem. (But there are many things, "Hide bottom bar when pushed" is to toolbar).
Select your "Navigation Controller" and in "Attribute Inspector" remove the checkmark from "Under Bottom Bars".
IF you can't select bottomlayoutguide bottom in your Xcode 7+
just do the following:
open your storyboard in source code editor
search your controller's identifier
find <layoutGuides>, type <bottom>, copy it id
search by id
change attribute from top to bottom
enjoy.
In the storyboard, Go to the View Controller that you want to hide the tab bar, click on Attribute Inspector and select Hide bottom bar when pushed. Check image bellow.
If you want the tab bar to be hidden, you can add this code to your controller,
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.tabBarController.tabBar.hidden = YES;
}
You will also have to put that code (but passing NO) into the controller where you want the tab bar to be visible. You should also deselect the "Hide bottom bar when pushed" box in IB.
After Edit:
You'll get a better animation if, in the first controller, you animate the alpha value of the non-hidden tab bar from 0 to 1 over a short time. This looks good if you go back with the back button. If you want to use the swipe back, you would have to do something more complicated involving the interactivePopGestureRecognizer.
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.tabBarController.tabBar.hidden = NO;
self.tabBarController.tabBar.alpha = 0.0;
[UIView animateWithDuration:.4 animations:^{
self.tabBarController.tabBar.alpha = 1.0;
}];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.tabBarController.tabBar.hidden = NO;
self.tabBarController.tabBar.alpha = 0.0;
[UIView animateWithDuration:.3 animations:^{
self.tabBarController.tabBar.alpha = 5.0;
}];
}
set UINavigationBar Translucent with NO.
like this: self.navigationController.navigationBar.translucent = NO;
Try pinning bottom of your view to bottom of superview and not bottom-layout

top navigation bar becomes visible when navigation back from push segue on iphone

I'm hiding the navigationbar on a certain view, and when the user presses a button on the view, i'm pushing it to the next view.
In the next view, I am not longer hiding the nav bar and as expected it becomes visible. When hitting back however, the navbar on the first view also becomes (somehow) visible.
I'm hiding the top navbar like this:
self.navigationController.navigationBar.hidden = YES;
And I'm making it visible like this:
self.navigationController.navigationBar.hidden = NO;
I wonder what could be wrong with this, as it's quite basic but somehow has a glitch.
In Parent VC's viewWillAppear method hide the navigation bar.
-(void)viewWillAppear:(BOOL)animated {
self.navigationController.navigationBar.hidden = YES;
}

Black area with interactivePopGestureRecognizer when popping a view controller with visible nav bar to a one with hidden nav bar

I have this ViewController #1 which is the root view controller of a navigation controller and has
self.navigationController.navigationBarHidden = YES;
ViewController #1 tells its navigation controller to push ViewController #2, which has
self.navigationController.navigationBarHidden = NO;
When I want to go back from ViewController #2 to ViewController #1 by swiping from the left side of the screen, I see my views as the screenshot I attached here. This is captured as I move my finger to the right, so as I keep swiping to the right, the black area on the top right gets smaller and smaller until ViewController #1 covers all the screen area.
I'm guessing that this is caused by the hidden/visible navigation bar difference between the two view controllers.
I'd like to learn if it's possible to get rid of this black area.
As discussed with HoanNguyen, I had put my code to hide/show the navigation bar on viewWillAppear/Disappear but finally I figured out that the trick was to set the values animated. Weird, but this solved my problem and the black area is now gone:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:self.shouldHideNavBar animated:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigationController setNavigationBarHidden:!self.shouldHideNavBar animated:animated];
}
You should put your code set hidden/shown navigation in viewWillAppear or viewDidAppear.

alternating between toolbar / tab bar

my app is structured as follow: UITabBarController > UINavigationController > ViewControllerOne > ViewControllerTwo.
the UINavigationBar has at the bottom the tab bar, now when the user navigates into the second view controller, i want to be able to hide the tab bar and replace is with a tool bar. i tried this code:
[self.navigationController.tabBarController.tabBar setHidden:YES];
[self.navigationController.toolbar setHidden:NO];
when i run the app the tab bar is hidden but the toolbar doesn't appear. plus, since the last VC is a table view controller, when i scroll through the cells there is a white gap between the table and the bottom of the view. how can i fix that?
That won't work because when you hide the tab bar like that the subviews won't be adjusted properly (that's why you get the white space). You'll have to use
self.hidesBottomBarWhenPushed = YES;
In your init method or awakeFromNib... and then
[self.navigationController setToolbarHidden:NO animated:YES];
In the viewDidLoad for example.
That way the tab bar controller's view is going to layout correctly it's subviews when you hide the tab bar. Just remember to call self.hidesBottomBarWhenPushed = NO; in your first view controller otherwise the tab bar is still going to be hidden when the second view controller is popped from the navigation stack.
Try to assigning toolbar with appropriate frame and adding it to self.tabBarController.view

Resources