views:

1061

answers:

2

I would like to have the navigation bar hide more slowly than usual.

I tried the following, but when hiding, it disappears instantly instead of animating out (the view below does animate up correctly):

[UIView beginAnimations:@"hideNavBar" context:nil];
[UIView setAnimationDuration:2.0];
[self.navigationController setNavigationBarHidden:value];
[UIView commitAnimations];

If I substitute:

[self.navigationController setNavigationBarHidden:value animated:YES];

Then it uses the usual duration instead of my slow version. Hmmph.

I even tried to get really crafty and do:

CGFloat *durationRef = &UINavigationControllerHideShowBarDuration;
CGFloat oldDuration = *durationRef;
*durationRef = 2.0;
[self.navigationController setNavigationBarHidden:value animated:YES];
*durationRef = oldDuration;

Which resulted in a EXE _ BAD _ ACCESS on the assignment. Any ideas?

A: 

If you want to change the duration you need to implementation your own. UINavigationBar is a view, you can grab its layer and move it around without the actual view. Basically you do something like this:

//This routine starts animating the layer of the navigation bar off screen
- (void)hideNavigationBar {
  CALayer *layer = self.navigationBar.layer;

  CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
  animation.duration = 4.0;
  animation.toValue = [NSNumber numberWithFloatValue:(layer.position.y - self.navigationBar.frame.size.height)];
  animation.delegate = self;
  [touchedLayer addAnimation:animation forKey:@"slowHide"];
}

//This is called when the animation completes. We have not yet actally
//hidden the bar, so on redraw it will snap back into blace. We hide it
//here before the redraw happens.
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL) finished {
  if (finished) {
    [self.navigationController setNavigationBarHidden:YES animated:NO];
  }
}

Animating the bar back in is similiar. Note that this will not scale any other views on screen as the bar moves, you will have to setup seperate animations on whatever other views need to adjust.

Changing the speed is a lot of work, UIKit is not setup to do it, and working around Apple's built in animations is like walking through landmines. Unless you have a really compelling reason to do it I think you will find the work to get everything behaving correctly is way more than it is worth.

Louis Gerbarg
In the end I decided that reimplemebting UINavController wasn't worth the small gain in elegance. Thanks for the answer though.
Andrew Pouliot
I don't think this works.
Alex Reynolds
Why wouldn't it? You are always free to grab the layers on screen and start attaching animations. For reference, I have done this while experimenting, but I have never shipped production code that does this.
Louis Gerbarg
A: 

you can still use

[UIView beginAnimations:@"FadeOutNav" context:NULL];
[UIView setAnimationDuration:2.0];
self.navigationController.navigationBar.alpha=0.0;
[UIView commitAnimations];
pop850