I am doing a custom UINavigationController pop transition animation.
But having a strange bug, I've made a sample project to demonstrate the issue (Taken from https://github.com/objcio/issue5-view-controller-transitions)
An navigation-based app, 2 view controllers.
The first viewController has 2 bar button items on the navigationBar, a button in the middle of view to push to second viewController.
The second viewController has a left bar button item to pop to the first viewController.
If the second view controller has been dragged less than 50%, my custom animation will cancel the transition, and if it's over 50%, it'll finish the transition, pop the viewController. (Just like the system default)
However, if the transition was cancelled, the navigation item's on the first view controller will be over-ridded.
The "back" item will appear on first view controller, and the right bar button item will disappear.
This is the video to demonstrate: https://youtu.be/qg2lUKsNtzk
And the source code is on github: https://github.com/JohnnyTseng/issue5-view-controller-transitions
Could somebody point out where the problem is? I've been debugging this issue for whole day. Thanks!
In iOS 7 Apple add new default navigation behavior. You can swipe from left border of the screen to go back on navigation stack.
you can stop this by putting this code in application delegate.
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
you can read more over here interactive pop gesture of navigation view controller
Related
The pushed controller cross over current controller.
Results are as follows:
image 0
Actually, I have hook into this app, it use a subclass named MMUINavigationController,
and I am sure current action is "pushViewController:animated:", it's the interface I hooked.
Tweak.xm:
image 1
alertView:
image 2
how to make it ?
additional,standar animation:
image 3
navigation bar of pushed controller
image 4
Here's one solution:
hide the navigation bar of the navigation controller
add a navigation bar to the root view controller of the navigation controller
restore the swipe to back gesture to the navigation controller
For the last point you can add a pan gesture recognizer (suggested) or simply set the interactivePopGestureRecognizer's delegate of the navigation controller to nil:
self.navigationController?.interactivePopGestureRecognizer?.delegate = nil;
but please refer to this discussion for its implications: No Swipe Back when hiding Navigation Bar in UINavigationController
EDIT:
Working solution which fulfills the requirements: just setting the navigationBarHidden in the viewWillAppear does the magic.
I've setup a sample demo here: https://github.com/ldantona/NavigationBarExample
EDIT 2:
Just found this library, could it be of any help?
https://github.com/MoZhouqi/KMNavigationBarTransition
The library can capture the background style of the navigation bar in
the disappearing view controller when pushing, and when you pop back
to the view controller, the navigation bar will restore the previous
style, so you don't need to consider the background style after
popping. And you also don't need to consider it after pushing, because
it is the view controller to be pushed that needs to be considered.
Hope it helps
I have a UIViewController that I display full screen, then when the user touches a button I present another view controller like so:
[self.navigationController pushViewController:loadSaveViewController animated:YES];
I like the animation that happens when I transition TO the view controller i.e. the main view shifts down and slides off to the left and the new view controller is displayed with the nav bar at the top.
HOWEVER, when I go back using the button at the top of the nav bar the screen does the opposite. The main screen appears, but with a nav bar at the top for a short time then the main screen shifts up.
How do I stop the main screen from doing the animation? When the user returns to the main screen, I do not want them to see the nav bar and the shift up, I just want the main screen to appear, or slide in.
Thanks for the help.
In iOS 7, there are new classes that will allow you to control every aspect of animation. This website is very useful ios 7 transitioning
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'm using a Container View control through interface builder to embedded a UINavigationController and its stack into my app.
The problem I'm having is that the back button does not work on all pushed VCs over the Root VC.
You press the automatically generated back button on these pushed VCs and nothing happens.
Edit:
There is no code written. Its all set up in IB at the moment.
As you can see...Container View with its embedded view controller set to the UInavigation Controller. The whitespace on the left will be a swipeable menu eventually - thats the reason for the set up. Then there's a next button on the root RV which segues to a second view controller.
That state is shown above. Pressing the back button (labelled test) does nothing. Normally it would pop the top view controller and go back to 'test'. Clearly the embedding is interfering with the normal UINavigiationController function somehow.
I just dont know how.
Another Edit:
Making a custom button on that top View Controller and manually calling
[self.navigationController popViewControllerAnimated:true];
Actually works and the top view controller is removed from the stack.
So the question is why does the back button not work?
I had a similar problem when I forgot that I added a tap gesture recognizer to my navigation bar. The back button actually received touches (pushed state) but as in your example did nothing. A custom button on the navigation bar worked though.
Once I removed the gesture recognizer the back button worked again.
Maybe some other view/or gesture recognizer in your container view is catching the touches...
I have an app in which there is a ViewController and once a button is pressed it goes to DetailViewController. In ViewController I have hidden the navigation bar to have more room to display an image while in DetailViewController it is necessary.
When I hit the back button in DetailViewController it goes back, however since it has a navigation bar and ViewController doesn't the animated segue looks bad. I was wondering, is there a way to make the default back button (that comes when embedded into navigation controller) give you a non animated segue?
Thanks
try using [[self navigationController] setNavigationBarHidden:{YES,NO} animated:{YES,NO}]; in view{Will,Did}{Dis}appear instead of setting everything up via Xcode UI controls
You can get good results WITH animation using them too.
If you really want to remove the whole animation, though: Prevent the animation when clicking "Back" button in a navigation bar?