I have an iOS App, designed within a UINavigationController. One of the pushed view controllers, however, needs a full screen view, without the navigation bar on the top. (to get back, there is just a small, circular button). However, any method I've tried of 'hiding' the navigation bar (navigationCtl.navigationBar.hidden=TRUE) leaves me with ugly artifacts - calling that before the view is pushed (in viewDidLoad or viewWillAppear) causes the previous view controllers bar to flash white just as the slide left animation starts. Similarly, calling it in viewDidAppear leaves a white bar at the top of the second view, along with several subviews pushed down, out of the way. Is there any way I can just have the new view slide over as it usually does, but when it comes over, there's simply no navigation bar up top?
Please note, to help Google, essentially the question here is:
How to animate between two UIViewControllers, when one has a navigation bar at the top, and the other one does not have a navigation bar at the top. So, how to navigate from a UIViewController with a navbar to one without a navbar - avoiding the horrible flickering.
The amazing answer is given below by Ev ... awesome.
give this a spin and see how it works for you.
in the destination view controller in viewWillAppear
- (void)viewWillAppear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
It actually has a cool effect and can be useful. in the viewWillAppear everything happens before the view is displayed so it takes away the strange artifacts.
be well
Related
I'm making an app in Swift and even though i'm using a navigation controller, there is a particular point where I want to present a view controller rather than make a segue and have the viewController added to the navigation stack.
This view controller i'm presenting is completely disconnected from the rest of the storyboard (it gets reused by a few screens).
To "fake" that it's part of the navigation controller stack, I wanted to drag and drop a navigation bar onto this orphaned view controller, and then manually add a back button. I want to handle my own back functionality and then use self.dismissViewControllerAnimated(true, completion: nil) to go back.
The problem is that this navigation bar doesn't have the same height or feel as the traditional one - the back button is way up high almost hitting the carrier/bars of service/4g/LTE area, and the title is touching the top of the screen. It's too high.
If I manually move it down, it's height doesn't occupy the whole area and there is this weird white strip.
Any ideas on how I can drag&drop my own navigation bar and get it to look like the ones typically done when you have a navigation controller?
Thanks!
Can you wrap your controller in a navigation controller, and present the nav controller modally:
UINavigationController *modalNavcontroller = [[UINavigationController alloc] initWithRootViewController:youController];
[self presentViewController:mdalNavcontroller animated:YES completion:nil];
I'm having weird view controller issues when using the -hidesBottomBarWhenPushed property. This is an iOS 7 only project. Using Xcode 5.whatever is latest. No betas.
There are several issues, but I think they are all surrounding the same issue. Here are my different use cases.
Both Use Cases start with the same layout. UITabBarController (2 tabs) --> UINavigationController (Tab1) --> Tab2 (not needed for example) --> set as rootViewController on my application window.
Use Case 1:
ViewController1 - Has navigation controller and tableview with content. Push a view controller that does not need the tab bar (uses toolbar with custom content).
ViewController2 - Tab bar is not showing, things look great so far. Now I need to push another view controller that needs the tab bar again.
ViewController3 - Tab bar is showing, things are still good to go. One more level to go, tab bar still needs to show.
ViewController4 - Tab bar is missing. Not good. This sucks, lets back up.
ViewController3 - Tab bar is now gone here too. View takes up full space, that is good, but no tab bar. Back we go.
ViewController2 - What the eff? My toolbar is shaded and can't be selected, and the view is sized like there is a tab bar there. I can scroll content and see where it thinks the view ends. This view is toast, back to home.
ViewController1 - Everything is back to normal. Tab bar showing no problem. I can drill back in with no issues going in, but coming back, everything is hosed pretty bad.
Use Case 2:
We can skip a view and get similar results.
ViewController1 - Same as Use Case 1. Our home view, where everything is working and looks great.
ViewController3 - Lets skip the toolbar view and keep our tab bar in place. No sweat. Tab bar shows up fine. Looks good, lets drill in one more level.
ViewController4 - The hell? Tab bar is here, but it looks shaded or selected. Content is offset up from the tab bar, it doesn't line up with the tab bar. About the same height as the tab bar. If we toggle tabs, the tab bar loses its shaded state. Come back to same screwed up view... looks fine now. The table view here is now nested perfectly on top of the tab bar. I give up!!
ViewController3 - The tab bar here looks fine at least. Whew! One less thing to fix.
ViewController1 - Home still looks good. Please don't ever leave me home view.
Those are the steps I take. Now for how I'm pushing these views.
ViewController1 - Does most of the heavy lifting. Due to examples and fixes from other questions, is setting the -hidesBottomBarWhenPushed property before pushing views out the door.
All View Controllers have a property set during init, self.hidesTabBar; YES hides it, NO shows it.
ViewController2 alloc/init; // normal init stuffs
// set current view property to the property on next views property (set in init of view)
[self setHidesBottomBarWhenPushed:ViewController2.hidesTabBar];
[self.navigationController pushViewController:ViewController2 animated:YES];
// set back after pushing to what the current view needs to be at
[self setHidesBottomBarWhenPushed:self.hidesTabBar];
This method continues for all views being pushed onto the nav stack. Basically, before I push, I set my current view -hidesBottomBarWhenPushed property to the same as the view I'm about to push. After I push, I set it back to what it was before I pushed.
I have tried every combination of setting this and I end up with problems all over. I need to be able to control when the tab bar gets shown. Some cases it will always be up. Some it will show/hide/show/show, and every combination in between. The only constant is that it will always be shown on the root/first view of the navigation stack. After that, it all depends on the path the user takes. Help!!!
After filing a radar, it seems that Apple has acknowledged that this is a bug in iOS 7. They are reporting it is fixed in iOS 7.1b4. I have also confirmed this is fixed in that build as well.
My app is based around a UINavigationController. On some screens I have a UITabBarController embedded within. When I go to a screen with the tab bar everything works fine on the first tab. (each tab is a UITableViewController) I can tap a cell of the table view and it'll take me to the next page by correctly pushing it onto my nav controller. If I go to another tab it loads the table view fine, but if I tap a cell to take me to another view I get this error:
Nested push animation can result in corrupted navigation bar
Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
It pushes on the next page, but then if I attempt to press the back button on the nav bar the app will crash.
How could I go about fixing this? I looked at multiple other responses to similar problems, but none of them have helped me with this.
It would be really helpful if you share your code.
However this may be helpful for you:
while using tab bar , you should try that every single tab has its own navigation controller and use individual navigation controller to move to specific viewcontrller of specific tab. I know its hard to understand like this..
For e.g in app del you have your main navigation controller using which you push to next view controller ,say "SecondViewController".
Now this second one has got one tab bar with 4 tabs tab1,tab2,tab3,tab4. now each tab can have any no of view controllers associated with them. For e.g on tab1,you move to another screen and again from there to next screen and so on.
So to manage them there should be separate navigation controllers like,tab1nav,tab2nav,tab3nav,tab4nav.
tabBarController.viewControllers = [NSArray arrayWithObjects:"tab1nav".....and so on all nav, nil];
Now depending in which tab you are, use that tab's navigation controller to move to next screen of that tab or move back.
If you have viewDidAppear function,
Remember to put [super viewDidAppear:animated]; inside the function.
In Apple's recently released Remote app I noticed the way in which the navigation bar behaves is unique and I haven't been able reproduce it. When popping the Now Playing view controller the navigation bar remains transparent for the Now Playing view controller and the navigation bar for the library view controller also stays translucent (Screenshot 1). I'm trying to figure out if they are using two navigation controllers or only one. Personally I feel they're using just one for two reasons (1) the interactive pop gesture is enabled; (2) when you press the 'Now Playing' button in the library view controller, just before the now playing screen has finished 'push view controller' animation the navigation bar becomes transparent (Screenshot 2). This is the behaviour I experience when pushing my view controller (which sets the navigation bar to transparent). So my question is: How does Apple present both navigation bars of the two view controllers as if they were individual (as with Screenshot 1), even the bar buttons, navigation title etc... are 100% in opacity when switching (usually when pushing/popping the buttons and titles of the previous view controller fade as the new controller is being pushed). I've tried playing around with the bar tint colour in viewDidAppear and viewWillAppear in both view controllers but cannot reproduce the same behaviour, and cannot prevent the bar buttons from fading.
Gosh I hope I've explained this well, I get confused just thinking about it!
Screenshot 1 (Popping):
Screenshot 2 (Pushing):
I just downloaded the application to make sure. Two different navigation bars are used. You can see this by using the interactive pop gesture. Notice how the navigation bar on the bottom view controller slides in and out. During normal push and pop transitions, the navigation items just fade in and out on the existing bar, while the bar is stationary. This is what happens up until the point where the now playing view controller is pushed.
If you look quickly, during the now playing view controller animation, you can see the bottom navigation bar disappear.
From my experience with UIKit behavior and what I see in the app, here is what I think happens:
album_vc = the bottom, list view controller
nowplaying_vc = the top view controller
On nowplaying_vc's viewWillAppear:
Set the navigation bar to hidden using [self.navigationController setNavigationBarHidden:YES animated:YES];. Since this is in animation block, this will make the navigation bar slide out during the push animation.
Set [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; Pretty sure about this, because notice there is no animation in the transition of the status bar styles. It just becomes white.
On nowplaying_vc's viewWillDisappear:
Set the navigation bar to shown using [self.navigationController setNavigationBarHidden:NO animated:YES];. Since this is in animation block, this will make the navigation bar slide in during the pop animation.
Set [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleDefault; Again, notice how during interactive pop gesture, the status bar just changes with no animation.
To achieve the transparent look of the navigation bar of nowplaying_vc, you can use an empty image ([UIImage alloc]) with setBackgroundImage:forBarPosition:barMetrics:.
Since the application does not rotate, we can't be sure if the navigation bar on nowplaying_vc is part of another navigation controller or just a navigation bar on the top with a position of UIBarPositionTopAttached. For all we know, there isn't even a navigation bar there but just a back chevron image view (back bar button is comprised of an image view and a button).
I think the status bar style is changed in viewWillAppear: and viewWillDisappear: due to the unnatural feel there is during interactive pop gesture. I would recommend using an animated transition, or even better, use the new view controller-based status bar style, which the system animates transitions by itself.
Update for modern API:
You should use the animateAlongsideTransition:completion: or animateAlongsideTransitionInView:animation:completion: API, rather than relying on the implicit animations of viewWillAppear: and viewWillDisappear:.
Instead of hiding and showing the navigation bar, you can update the alpha for the navigation bar. It will animate smoothly during the transition. For the view controller with transparent nav bar, instead of modifying the nav bar, create a navbar (or just the back button and title etc.) manually in the second controller's view. We will then hide the navbar when transitioning from first view controller to the second one.
On your first controller's viewWillDisappear and on your second view controller's viewWillAppear:, set the navigation bar alpha to zero using self.navigationController.navigationBar.alpha = 0;. Since this is in animation block, this will make the navigation bar disappear during the push animation.
Set the alpha back to one in first controller's viewWillAppear and second controller viewWillDisappear.
I'd like to use a slide up / down effect to display various viewControllers inside a navigation controller. A few other apps do this like square, and every day. Basically when the app loads, I want to display a base view in the navigation controller. Then slide up another view controller over top of it. When then hit a button in the nav bar, I want to slide that down and show the base controller, all the while retaining the navigation bar, and changing up nav items.
Originally I tried to make this work by showing a modal but that requires using a new nav bar.
Has anyone done this, or knows of a good example that illustrates this UI pattern? Thank you!
You could have UIViews in a UIScrollView