How to disable navigationBar animation? - ios

I have two UITableViewControllers such that when I click next on the first UITableViewController, the second UITableViewController gets pushed on the navigation stack and animates the transition like normal. I'd like to make it so when I push next, only the views animate, and the navigation bar doesn't (stays the same). I've gotten very close to doing this with the code below:
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
CATransition *navTransition = [CATransition animation];
navTransition.duration = .5;
navTransition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
navTransition.type = kCATransitionPush;
navTransition.subtype = kCATransitionPush;
[self.navigationController.navigationBar.layer addAnimation:navTransition forKey:nil];
}
I put this code, and I also make it so the title and buttons on both navigation bars are exactly same in each UITableViewController. It almost works, problem is, the navigation bar blinks when the animation occurs. Is there anyway to get it to not blink, or is there any other good way to prevent the animation of the navbar from occurring (ie disabling the animation on the layer or something)?
UPDATE: Anyone got any other ideas? Still struggling with this.

This is what I came up with. Here is the code for the first viewController in the sequence:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (viewController == self)
{
if (self.isInitialized)
{
CATransition *navigationBarAnimation = [CATransition animation];
navigationBarAnimation.duration = 1.5;
navigationBarAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];;
navigationBarAnimation.type = kCATransitionFade;
navigationBarAnimation.subtype = kCATransitionFade;
navigationBarAnimation.removedOnCompletion = YES;
[self.navigationController.navigationBar.layer addAnimation:navigationBarAnimation forKey:nil];
}
else
{
self.isInitialized = YES;
}
}
}
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (viewController == self)
{
if (self.isInitialized)
{
[self.navigationController.navigationBar.layer removeAllAnimations];
}
}
}
Here is the code for the 2nd view controller:
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (viewController == self)
{
if (!self.isInitialized)
{
CATransition *navigationBarAnimation = [CATransition animation];
navigationBarAnimation.duration = 1.5;
navigationBarAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];;
navigationBarAnimation.type = kCATransitionFade;
navigationBarAnimation.subtype = kCATransitionFade;
navigationBarAnimation.removedOnCompletion = YES;
[self.navigationController.navigationBar.layer addAnimation:navigationBarAnimation forKey:nil];
self.isInitialized = YES;
}
}
}
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (viewController == self)
{
if (self.isInitialized)
{
[self.navigationController.navigationBar.layer removeAllAnimations];
}
}
}
You have to use the UINavigationController delegate methods to figure out when the UIViewController is being shown. Then for each UIViewController, need to make a BOOL isInitialized property so it helps you determine when the UIViewController is being pushed on the stack, or when it's being shown because you pushed back on the next UIViewController.

This may not be the best answer/idea but you could just mask the UINavigationBar during the animation.
Create a UINavigationBar that looks exactly the same way as your current UNavigationBar add it to the keyWindow just before the transition takes place, then after it is finished remove it. This will essentially cover just the UINavigationBar and hide its animation.

Swift
Here is solution in swift
var isInitialized = false
Your FirstViewController:
func navigationController(_ navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
if viewController == self {
if self.isInitialized {
var navigationBarAnimation = CATransition()
navigationBarAnimation.duration = 1.5
navigationBarAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
navigationBarAnimation.type = kCATransitionFade
navigationBarAnimation.subtype = kCATransitionFade
navigationBarAnimation.removedOnCompletion = true
self.navigationController?.navigationBar?.layer?.addAnimation(navigationBarAnimation, forKey: nil)
}
else
{
self.isInitialized = true;
}
}
}
func navigationController(_ navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
if viewController == self {
if self.isInitialized {
self.navigationController?.navigationBar?.layer?.removeAllAnimations()
}
}
}
Your SecondViewController:
func navigationController(_ navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
if viewController == self {
if !self.isInitialized {
var navigationBarAnimation = CATransition()
navigationBarAnimation.duration = 1.5
navigationBarAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
navigationBarAnimation.type = kCATransitionFade
navigationBarAnimation.subtype = kCATransitionFade
navigationBarAnimation.removedOnCompletion = true
self.navigationController?.navigationBar?.layer?.addAnimation(navigationBarAnimation, forKey: nil)
self.isInitialized = true;
}
}
}
func navigationController(_ navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
if viewController == self {
if self.isInitialized {
self.navigationController?.navigationBar?.layer?.removeAllAnimations()
}
}
}

Related

Transition animation from one view controller to another view controller

I have 2 view controller with navigation controller. I'm pushing one firstViewController to secondViewController. i'm currently using
[self.navigationController pushViewController:detailsViewController animated:YES];
but the transition is secondView come in from the right. What i'm trying to do is secondView come in from the back and firstView fading out while secondView fading in.
Is there anyway to achieve this?
Push/Pop UIVIewController FadeIn/FadeOut in Swift
class FadeInPushSegue: UIStoryboardSegue {
var animated: Bool = true
override func perform() {
if var sourceViewController = self.sourceViewController as? UIViewController, var destinationViewController = self.destinationViewController as? UIViewController {
var transition: CATransition = CATransition()
transition.type = kCATransitionFade; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
sourceViewController.view.window?.layer.addAnimation(transition, forKey: "kCATransition")
sourceViewController.navigationController?.pushViewController(destinationViewController, animated: false)
}
}
}
class FadeOutPopSegue: UIStoryboardSegue {
override func perform() {
if var sourceViewController = self.sourceViewController as? UIViewController, var destinationViewController = self.destinationViewController as? UIViewController {
var transition: CATransition = CATransition()
transition.duration = 0.4
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionFade; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
sourceViewController.view.window?.layer.addAnimation(transition, forKey: "kCATransition")
sourceViewController.navigationController?.popViewControllerAnimated(false)
}
}
}

How to persist navigationItem.titleView between screen?

I am using NavigationController to manage three screens. All three screens share a common image as title. I set the image in the viewWillAppear in each VC as follow:
self.navigationItem.titleView = myImageView
The problem is whenever a screen is pushed/popped, the navigation is animated and a new image will come from right or left. I want the image to persist and remain in the middle none-animated.
Is there a way to disable this animation?
It's reproducible, only if you place/setting titleView code in viewWillAppear. it's moving because viewWillAppear called during forth(push) & back(pop) both operation. Set it into viewDidLoad, it will fix this issue
override fun viewDidLoad() {
super.viewDidLoad()
self.navigationItem.titleView = myImageView
}
One more alternate solution for this problem is
var isViewDidLoadCalled = false
override fun viewDidLoad() {
super.viewDidLoad()
isViewDidLoadCalled = true
}
override fun viewWillAppear(_ animated: Bool) {
super. viewWillAppear(animated)
if (isViewDidLoadCalled) {
self.navigationItem.titleView = myImageView
isViewDidLoadCalled = false
}
}
I recommend to use, viewDidLoad to setup your titleView
Another hard but feasible solution is:
You need to use the UINavigationController delegate methods to find out when the UIViewController is being shown. Then for each UIViewController, need to make a boolean variable like isInitialized property, which help you to determine when the UIViewController is being pushed on the stack, or when it's being shown upon back of next view controller.
Your FirstViewController:
func navigationController(_ navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
if viewController == self {
if self.isInitialized {
var navigationBarAnimation = CATransition()
navigationBarAnimation.duration = 1.5
navigationBarAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
navigationBarAnimation.type = kCATransitionFade
navigationBarAnimation.subtype = kCATransitionFade
navigationBarAnimation.removedOnCompletion = true
self.navigationController?.navigationBar?.layer?.addAnimation(navigationBarAnimation, forKey: nil)
} else {
self.isInitialized = true;
}
}
}
func navigationController(_ navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
if viewController == self {
if self.isInitialized {
self.navigationController?.navigationBar?.layer?.removeAllAnimations()
}
}
}
Your SecondViewController:
func navigationController(_ navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
if viewController == self {
if !self.isInitialized {
var navigationBarAnimation = CATransition()
navigationBarAnimation.duration = 1.5
navigationBarAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
navigationBarAnimation.type = kCATransitionFade
navigationBarAnimation.subtype = kCATransitionFade
navigationBarAnimation.removedOnCompletion = true
self.navigationController?.navigationBar?.layer?.addAnimation(navigationBarAnimation, forKey: nil)
self.isInitialized = true;
}
}
}
func navigationController(_ navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
if viewController == self {
if self.isInitialized {
self.navigationController?.navigationBar?.layer?.removeAllAnimations()
}
}
}

iOS 7 change pushviewcontroller animation direction

When i push a viewcontroller the animation is always from right to left. I want to change that animation to the inverse left to right.
I have tried this code but doesnt work. The animation is still from right to left. How can i achive this simply and correctly? Need help please. Thanks in advance.
//NOT WORKING
myViewController *mController = [self.storyboard instantiateViewControllerWithIdentifier:#"myViewController"];
CATransition *transition = [CATransition animation];
transition.duration = 0.3;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[self.view.layer addAnimation:transition forKey:nil];
[self.navigationController pushViewController:mController animated:YES];
Since this question mentions iOS 7 I'm quite surprised the answer doesn't mention the Animated Transitions API introduced in iOS 7.
If you want to get straight into GitHub the objc.io guys have a great post with a linked project here
Take a look at the documentation and you will see the following:
#availability(iOS, introduced=7.0)
optional func navigationController(navigationController: UINavigationController,
animationControllerForOperation operation: UINavigationControllerOperation,
fromViewController fromVC: UIViewController,
toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning?
Or in Objective-C
- (id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC NS_AVAILABLE_IOS(7_0);
What this means is that from iOS 7 you can control how the navigation controller implements its animations for pushes and pops.
All that is needed is for you to set the delegate of the navigation controller and vend the correct animator object when appropriate. So lets get started:
1. Set the UINavigationControllerDelegate
I typically like to have an App-Wide Navigation Coordinator that manages all my transitions etc. So ideally you want some object that will be alive for the duration of the NavigationController. So we might have a coordinator that looks like this:
class NavigationCoordinationController: NSObject {
private(set) var navigationController:UINavigationController
required init(navigationController: UINavigationController) {
self.navigationController = navigationController
super.init()
navigationController.delegate = self
}
}
I typically create this in the App Delegate so it can be referenced anywhere. You could also set the delegate on a per view controller basis, creating a custom UINavigationController subclass, or wherever you see fit.
2. Create A Custom Animator
Now we need an object that conforms to the UIViewControllerAnimatedTransitioning protocol. This object will be called upon to apply the animation whenever an animated transition is needed. This example is a simple animation that fades and expands the fromView in the transition so its relevant for a Push.
class CustomPushExpansionTransitioner: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval {
return 1
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let fromView: UIView = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
let toView: UIView = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
let container = transitionContext.containerView()
container.addSubview(toView)
container.bringSubviewToFront(fromView)
toView.frame = container.convertRect(fromView.bounds, fromView: fromView)
UIView.animateWithDuration(transitionDuration(transitionContext),
animations: { () -> Void in
fromView.alpha = 0
fromView.transform = CGAffineTransformConcat(fromView.transform, CGAffineTransformMakeScale(1.3, 1.3))
}) { (complete) -> Void in
transitionContext.completeTransition(true)
}
}
}
3. Vend The Animator Where Necessary
Now we need to implement the UINavigationController delegate and vend our custom animator when needed.
extension NavigationCoordinationController: UINavigationControllerDelegate {
func navigationController(navigationController: UINavigationController, animationControllerForOperation operation: UINavigationControllerOperation, fromViewController fromVC: UIViewController, toViewController toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
switch operation {
case .Push:
return LaunchToHomeTransitioner()
case .Pop:
break
case .None:
break
}
return nil
}
}
And there you go, you now have total control over your UINavigationController transitions
You are actually doing it right, but as far as I understand from your code, you are not overriding the method:
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
So, you need to inherit from UINavigationController and override the above method.
Here's how I do it (push + pop):
Push:
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
UIView *theWindow = self.view ;
if( animated ) {
CATransition *animation = [CATransition animation];
[animation setDuration:0.45f];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromLeft];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
[[theWindow layer] addAnimation:animation forKey:#""];
}
//make sure we pass the super "animated:NO" or we will get both our
//animation and the super's animation
[super pushViewController:viewController animated:NO];
[self swapButtonsForViewController:viewController];
}
Pop :
- (UIViewController *)popViewControllerAnimated:(BOOL)animated {
UIView *theWindow = self.view ;
if( animated ) {
CATransition *animation = [CATransition animation];
[animation setDuration:0.45f];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromRight];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
[[theWindow layer] addAnimation:animation forKey:#""];
}
return [super popViewControllerAnimated:NO];
}
NextViewController *next = [[NextViewController alloc] initWithNibName:#"NextViewController" bundle:nil];
[UIView transitionWithView:self.navigationController.view
duration:0.75
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[self.navigationController pushViewController:next animated:NO];
}
completion:nil];
Try Above code
You can try this as well.
CATransition *transition = [CATransition animation];
transition.duration = 0.5;
transition.type = kCATransitionMoveIn;
transition.subtype = kCATransitionFromLeft;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.navigationController.view.layer addAnimation:transition forKey:kCATransition];
DrawingResultsViewController *dr = [DrawingResultsViewController createAndShowProfile:YES];
[self.navigationController pushViewController:dr animated:YES];
If some one is looking for the same answer in Xamarin.iOS (based on gran33 answer) :
public override void PushViewController(UIViewController viewController, bool animated)
{
if (animated)
{
CATransition animation = new CATransition()
{
Duration = 0.5,
Type = CAAnimation.TransitionPush,
Subtype = CAAnimation.TransitionFromTop,
TimingFunction = AMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut)
};
View.Layer.AddAnimation(animation, CALayer.Transition);
base.PushViewController(viewController, false);
}
}
public override UIViewController PopViewController(bool animated)
{
if (animated)
{
CATransition animation = new CATransition()
{
Duration = 0.5,
Type = CAAnimation.TransitionPush,
Subtype = CAAnimation.TransitionFromBottom,
TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut)
};
View.Layer.AddAnimation(animation, CALayer.Transition);
return base.PopViewController(false);
}
return base.PopViewController(animated);
}
For Swift 4.0+
1 - Create a extension:
extension UINavigationController {
func customPopView(_ viewController: UIViewController) {
let transition: CATransition = CATransition()
transition.duration = 0.3
transition.type = CATransitionType.push
transition.subtype = CATransitionSubtype.fromLeft
view.layer.add(transition, forKey: nil)
pushViewController(viewController, animated: false)
}
}
2 - Call:
self.navigationController?.customPopView(yourViewController)
Assuming myViewController is your view controller, pass custom transition to the nav controller layer.
CATransition *transition = [CATransition animation];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[self.navigationController.view.layer addAnimation:transition forKey:#"pushViewController"];
[self.navigationController pushViewController:myViewController animated:NO];

How do I cross dissolve when pushing views on a UINavigationController in iOS 7?

If I simply call the push method with:
[self.navigationController pushViewController:viewController animated:YES];
then it uses a push animation. How do I change it to use a cross dissolve animation, like I can with a modal segue?
I use an extension for easy reuse:
extension UINavigationController {
func fadeTo(_ viewController: UIViewController) {
let transition: CATransition = CATransition()
transition.duration = 0.3
transition.type = CATransitionType.fade
view.layer.add(transition, forKey: nil)
pushViewController(viewController, animated: false)
}
}
Notice how animated is false; when you set it to true, you still see the standard 'push' animation (right to left).
You can use a CATransition as demonstrated in this answer:
CATransition* transition = [CATransition animation];
transition.duration = 0.5;
transition.type = kCATransitionFade;
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[self.navigationController pushViewController:viewController animated:NO];
The UINavigationControllerDelegate protocol has a method that can return a custom UIViewControllerAnimatedTransitioning object which will control the animation between the two view controllers involved in the transition.
Create an Animator class to control the cross-dissolve transition:
class Animator: NSObject, UIViewControllerAnimatedTransitioning {
let animationDuration = 0.25
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return animationDuration
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let toVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to)
toVC?.view.alpha = 0.0
let fromVC = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from)
transitionContext.containerView.addSubview(fromVC!.view)
transitionContext.containerView.addSubview(toVC!.view)
UIView.animate(withDuration: animationDuration, animations: {
toVC?.view.alpha = 1.0
}) { (completed) in
fromVC?.view.removeFromSuperview()
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
}
}
}
And provide it in your UINavigationControllerDelegate:
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationControllerOperation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return Animator()
}
Here is a more in-depth tutorial: https://web.archive.org/web/20191204115047/http://blog.rinatkhanov.me/ios/transitions.html
SWIFT 3, 4.2 -- as of October, 2019
let transition = CATransition()
transition.duration = 0.5
transition.type = kCATransitionFade
self.navigationController?.view.layer.add(transition, forKey:nil)
You can set Push viewcontroller like this.
CATransition* transition = [CATransition animation];
transition.duration = 0.4;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
transition.type = kCATransitionFade;
[self.navigationController.view.layer addAnimation:transition forKey:#"kCATransition"];
[self.navigationController pushViewController:readerViewController animated:false];
You can set Pop viewcontroller like this.
CATransition* transition = [CATransition animation];
transition.duration = 0.4;
transition.timingFunction = [CAMediaTimingFunction
functionWithName:kCAMediaTimingFunctionEaseOut];
transition.type = kCATransitionFade;
[self.navigationController.view.layer addAnimation:transition
forKey:#"kCATransition"];
[self.navigationController popViewControllerAnimated:false];
Update Swift 5
Using prepare(for segue:) instead of pushViewController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// other preparations
let transition: CATransition = CATransition()
transition.duration = 0.3
transition.type = CATransitionType.fade
navigationController?.view.layer.add(transition, forKey: nil)
}
Following michaels answer you can use UINavigationController extension.. something like this
/// Create an animatied fade push with default duration time.
/// - Parameters:
/// - controller: Which controller are we pushing...?
/// - animationDuration: What's the animation duration - has a default
func pushViewControllerWithFade(_ controller: UIViewController, animationDuration: TimeInterval = .Animation.defaultAnimationTime) {
let transition: CATransition = .init()
transition.duration = animationDuration
transition.type = .fade
pushViewController(controller, withTransition: transition)
}
/// Custom transition animation for pushing view contorller
/// - Parameters:
/// - controller: Which controller are we presenting now?
/// - transition: The transition for the push animation
func pushViewController(_ controller: UIViewController, withTransition transition: CATransition) {
view.layer.add(transition, forKey: nil)
pushViewController(controller, animated: false)
}

How to stop UINavigationBar title from animating while push transition

Is there any way to stop the titleView on UINavigationBar to animate when I push/pop view controllers. TitleView for each screen is same (app's logo).
Currently when I push a view, titleView on the navigation bar also slide with the view.
Set the title of the navigation item in each view controller to an empty string and add UILabel subview to the navigation bar:
UILabel *titleLabel = [[UILabel alloc] initWithFrame:self.navigationController.navigationBar.bounds];
titleLabel.font = [UIFont fontWithName:#"Avenir-Roman"
size:20.f];
titleLabel.text = #"TEST TITLE";
titleLabel.textAlignment = NSTextAlignmentCenter;
[self.navigationController.navigationBar addSubview:titleLabel];
This should give you a static title that doesn't move when switching between view controllers.
Try,
[self.navigationController pushViewController:viewController animated:NO];
- (void)viewDidLoad
{
self.navigationItem.title=#"";
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
Swift
A feasible solution is:
Use UINavigationController delegate methods to find out when the UIViewController is being shown. Then for each UIViewController, need to make a boolean variable like isInitialized property, which help you to determine when the UIViewController is being pushed on the stack, or when it's being shown upon back of next view controller.
Your FirstViewController:
func navigationController(_ navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
if viewController == self {
if self.isInitialized {
var navigationBarAnimation = CATransition()
navigationBarAnimation.duration = 1.5
navigationBarAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
navigationBarAnimation.type = kCATransitionFade
navigationBarAnimation.subtype = kCATransitionFade
navigationBarAnimation.removedOnCompletion = true
self.navigationController?.navigationBar?.layer?.addAnimation(navigationBarAnimation, forKey: nil)
}
else
{
self.isInitialized = true;
}
}
}
func navigationController(_ navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
if viewController == self {
if self.isInitialized {
self.navigationController?.navigationBar?.layer?.removeAllAnimations()
}
}
}
Your SecondViewController:
func navigationController(_ navigationController: UINavigationController, willShowViewController viewController: UIViewController, animated: Bool) {
if viewController == self {
if !self.isInitialized {
var navigationBarAnimation = CATransition()
navigationBarAnimation.duration = 1.5
navigationBarAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
navigationBarAnimation.type = kCATransitionFade
navigationBarAnimation.subtype = kCATransitionFade
navigationBarAnimation.removedOnCompletion = true
self.navigationController?.navigationBar?.layer?.addAnimation(navigationBarAnimation, forKey: nil)
self.isInitialized = true;
}
}
}
func navigationController(_ navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
if viewController == self {
if self.isInitialized {
self.navigationController?.navigationBar?.layer?.removeAllAnimations()
}
}
}

Resources