Reputation: 14527
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.
Upvotes: 3
Views: 6916
Reputation: 79636
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()
}
}
}
Upvotes: 0
Reputation: 14527
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
.
Upvotes: 2
Reputation: 9453
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.
Upvotes: 1