Stop navigation bar from reappearing after rotate - ios

I have an app where the user can tap the screen and the navigation bar will fade out (I do this by setting the alpha to 0), but when the device is rotated the navigation bar reappears (I guess the alpha is reset to 1?). How can I prevent this behaviour?
The navigation bar stays hidden if I use [self.navigationController setNavigationBarHidden:YES animated:YES] instead, but that doesn't give me the fade effect I want.
Is there another way to do the fading effect?
Thanks

I assume you're animating out the navigation bar with the alpha? Why not hide the navigation bar once you're finished?
[UIView animateWithDuration:1.0
animations:^{
self.navigationController.navigationBar.alpha = 0;
} completion:^(BOOL finished) {
[self.navigationController setNavigationBarHidden:YES animated:NO];
}];

Related

Height of UINavigationBar changes after modal flip animation

I've noticed that when I segue to a Naviagtion Controller, the navigation bar jumps slightly right after the flip animation completes.
It only does this when I use a flip horizontal segue, and not when I use the default slide up animation.
Here is a GIF I've made to illustrate the problem (sorry about the tiny size!):
http://i.imgflip.com/3ym0y.gif
Take note of the Nav bar with the title "Modal" -- notice it jumps down ~20 pixels after the animation.
The example above was created with a fresh project -- I have not subclased UINavigationController or UINavigationBar. Here is the storyboard, in case it helps:
http://i.imgur.com/qFlK2oB.jpg
What am I missing?
Add this to viewWillAppear in the controller you're presenting modally:
- (void)viewWillAppear:(BOOL)animated
{
// Workaround #1 for jumpy navbar
[self.navigationController.navigationBar.layer removeAllAnimations];
}
And when dismissing the controller (so in the same controller as above):
// Workaround #2 for jumpy navbar
[UIView transitionWithView:self.navigationController.view
duration:0.75
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:nil
completion:nil];
[self dismissViewControllerAnimated:YES completion:nil];
See https://stackoverflow.com/a/19265558/254603

Hiding UINavigationBar and Status Bar issue

I'm trying to hide my NavigationBar and the Status Bar (slide up animation) and I'm running into an issue.
When the status bar is visible, the origin point of every element that is at 0 point (x: 0) means right underneath the statusbar. However, when the statusbar is hidden, the 0 (x: 0) point updates to accomodate the new space, and 0 (x: 0) means the absolute top of the screen.
When I hide the status bar and rotate into landscape, the view autosizes and everything is shifted to use the status bar's space, and throws off my animation:
if (![[UIApplication sharedApplication] isStatusBarHidden]) {
// Change to fullscreen mode
// Hide status bar and navigation bar
[[UIApplication sharedApplication] setStatusBarHidden:YES
withAnimation:UIStatusBarAnimationSlide];
[UIView animateWithDuration:animationDuration animations:^{
navBar.frame = CGRectMake(navBar.frame.origin.x,
-navBar.frame.size.height-20,
navBar.frame.size.width,
navBar.frame.size.height);
} completion:^(BOOL finished) {
[navBar setHidden:TRUE];
}];
} else {
// Change to regular mode
// Show status bar and navigation bar
[navBar setHidden:FALSE];
[[UIApplication sharedApplication] setStatusBarHidden:NO
withAnimation:UIStatusBarAnimationSlide];
[UIView animateWithDuration:animationDuration animations:^{
navBar.frame = CGRectMake(navBar.frame.origin.x,
0,
navBar.frame.size.width,
navBar.frame.size.height);
} completion:^(BOOL finished) {
}];
}
Any suggestions?
EDIT: Here's what the screen looks like after rotation's relayout: Image
You're confusing the subdivision of the screen into UIView areas a little bit.
When you're in a navigation controller, there are three views:
Navigation controller's "root" view
Inside that, the NavigationBar (which of course is a UIView
Also inside the navigation controller, a "content area" view
So the Nav controller is managing it's own root view. In that it is filling the space with a NavigationBar at the top, and the rest of the area with one big UIView for content.
When you push your view controller onto the navigation stack, the Nav controller is adding your root view as the content. So your entire "self.view" is completely contained within the Nav controller's "content" view.
And so, of course, when the Nav controller hides the navigation bar... the "content" view expands up to fill the space. And then that view tells your view "hey, there's more space than you're using so your view also expands up to completely fill the Nav controller's content view.
So your view's "0" point is always the top of your view. That never changes. What is changing is where "the top of your view" is relative to the top edge of the screen.
If you want your content to remain in same spot on screen when navbar is removed, then you're going to have to account for the fact that your "zero" point is now higher than it was when there was a nav bar pushing the content view down.

How do I draw main view underneath my UINavigationBar so when the bar shows/hides, the view is unaffected?

Here's the situation:
I am making an app for iPad w/ iOS 6 using Autolayout along with UINavigationController. What I am trying to do is:
Segue from one view controller to the next with a standard push segue.
When I arrive at the new view controller, hide the nav bar with animation.
As the nav bar hides, I want my view to not shift at all. In fact, I want my view to effectively be drawn underneath the nav bar from the beginning, so I'm left with no shifting or movement of content and no black bars. For reference, this is what happens in the Amazon Kindle app when you go into a book.
With my current code, the contents of my view shift up to fill in the void left by the UINavigationBar.
I've tried force-setting the frame of my UIViewController's view and my UINavigationController's view to the entire iPad screen in the viewWillAppear method of my viewcontroller but no dice. I've experimented w/ Constraints in Autolayout but that also didn't get me to where I wanted to go.
Any help you can give would be great!
Try following before animating the navigation bar:
self.navigationController.navigationBar.alpha = 0.99f;
I didn't try this but this should work.
Looks like you need to add custom navigation bar in your new view and animate it to disappear.
I think, hiding original Navigation bar of Navigation Controller without shifting the view is not possible.
Rather add UINavigationBar to xib file, bind it to IBOutlet uiNavigationBar and try following code
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:NO];
}
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[UIView animateWithDuration:0.3f delay:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:^{
CGRect f = self.uiNavigationBar.frame;
f.origin = CGPointMake(f.origin.x, f.origin.y - 44);
self.uiNavigationBar.frame = f;
} completion:^(BOOL finished) {
NSLog(#"done");
}];
}

How to hide custom tab bar button when hidesBottomBarWhenPushed is "TRUE"

I am using the code snippet from Tito to add a custom button to my tab bar:
https://github.com/tciuro/CustomTabBar
(Subclassing UITabbarController and adding a custom button using
// .. created a UIButton *button
[self.view addSubview:button];
)
This works great with my storyboard-based app except for the case of a subview within a navigation controller with the option "Hides bottom bar on push" enabled.
This hides the tab bar as promised, but not the custom button.
Seems like the button should be added as a subview to the tab bar itself?
I tried this ugly code which did not even make the button show up:
for(UIView *view in self.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view addSubview:button];
break;
}
}
Any ideas?
UPDATE:
My solution:
In my ApplicationDelegate i define the following methods, which i call whenever needed in the viewWillAppear or viewWillDisappear methods:
-(void)hideCenterButton:(BOOL)animated
{
if(animated){
[UIView animateWithDuration:0.3
delay:0.0f
options:UIViewAnimationCurveLinear
animations:^{
CGRect frame = self.centerButton.frame;
frame.origin.x = -100;
self.centerButton.frame = frame;
}
completion:^(BOOL finished){
}];
}
}
-(void)showCenterButton:(BOOL)animated
{
if(animated){
[UIView animateWithDuration:0.35
delay:0.0f
options:UIViewAnimationCurveLinear
animations:^{
CGRect frame = self.centerButton.frame;
frame.origin.x = (self.view.superview.frame.size.width / 2) - (self.centerButton.frame.size.width / 2);
self.centerButton.frame = frame;
}
completion:^(BOOL finished){
}];
}
}
I had to set the animation's duration to 0.35s to get a smooth effect in harmony with the tab bar.
Why don't you make button your tabbar's part.
tabBarController.tabBar.addSubView(yourButton)
everything would be solve. cheers!
One easy way to handle this would be to create an instance of the button in .h of your file.
UIButton *customTabButton;
When calling the hides bottom bar on push set the button property to hidden and reset it again in the other views if the bottom bar is visible.
shareFbButton.hidden=YES;
You can check this is the viewDidLoad of all the files and put this line of code if needed to make sure you are displaying the button and hiding the button on all the pages you need.
if(self.tabBarController.tabBar.isHidden){
// set or reset the custom button visibility here
}
This is one way.
I think there are 2 ways you can got with this.
1) try to get the button into a view that is above the old top view controller and the tab bar BUT below the new top view controller that is pushed.
2) animate away the button when the new view controller is pushed.
The first will require mucking with the iOS proprietary view hierarchy which is undocumented, unsupported and could change anytime.
The second will be a matter of making the animation appear smooth enough for your user not to notice. It's not entirely a matter of behaving perfect, just appearing appropriately.
I would personally recommend an animation of the the button disappearing (animate it's alpha to 0) and reappearing based on if your view controller that goes over the tab bar is appearing or disappearing.
The animation for a navigation is (I believe) 0.3 seconds. If the button is in the middle of the tab bar, you'll likely want it invisible as the animating in view controller reaches it (if not sooner) so something between 0.1 and 0.15 seconds could be used to animate it out.
Now this does not make the button behave exactly the same as the tab bar, but with the quickness of the transition being so short, it will be unnoticeable really to the user.
Now just to provide a question for you to ask yourself. Why do you need to push a view controller that overlaps the tab bar? Why is that more desirable/necessary than presenting a modal view controller? If you can strongly argue for it, keep at it and good luck, if it's not necessary however, you may be able to achieve the experience you want with a modal view controller.
Check this one to put a button on the UITabBar. See if it works after with hidesBottoBarWhenPushed.

Default iOS UINavigationBar animation isn't smooth

I'm working on an application and need to hide the UINavigationBar (and toolbar) to provide a fullscreen mode in the in-app browser.
When the app run this code the animation work just fine.
[self.navigationController setNavigationBarHidden:YES animated:YES];
[self.navigationController setToolbarHidden:YES animated:YES];
When I want to exit from the full-screen mode the animation isn't smooth at all.
[self.navigationController setNavigationBarHidden:NO animated:YES];
[self.navigationController setToolbarHidden:NO animated:YES];
During the animation a black rectangle is visible under the navigation bar, I think it is the UIWebView that resize itself (the toolbar animation work just fine.)
Any idea on how I can solve this problem?
Instead of using setNavigationBarHidden:animated: for hiding the navigation bar, try this:
In your view controller's viewDidLoad compute different frames for your navigation bar and your view:
// The normal navigation bar frame, i.e. fully visible
normalNavBarFrame = self.navigationController.navigationBar.frame;
// The frame of the hidden navigation bar (moved up by its height)
hiddenNavBarFrame = normalNavBarFrame;
hiddenNavBarFrame.origin.y -= CGRectGetHeight(normalNavBarFrame);
// The frame of your view as specified in the nib file
normalViewFrame = self.view.frame;
// The frame of your view moved up by the height of the navigation bar
// and increased in height by the same amount
fullViewFrame = normalViewFrame;
fullViewFrame.origin.y -= CGRectGetHeight(normalNavBarFrame);
fullViewFrame.size.height += CGRectGetHeight(normalNavBarFrame);
When you want to go fullscreen:
[UIView animateWithDuration:0.3
animations:^{
self.navigationController.navigationBar.frame = hiddenNavBarFrame;
self.view.frame = fullViewFrame;
} completion:^(BOOL finished) {
}];
When you want to return to normal:
[UIView animateWithDuration:0.3
animations:^{
self.navigationController.navigationBar.frame = normalNavBarFrame;
self.view.frame = normalViewFrame;
} completion:^(BOOL finished) {
}];
Tested this in the iOS 5.1 emulator. Hope you can use that. The "black rectangle" must be the default background color of your window, i.e. a gap between your navigation bar and your view.

Resources