[iOS]自动添加NavigationController自定义按钮动画
2012-2-21
问题
UINavigationController顶部的返回按钮在切换视图时有左右滑动的动画(效果见iMail),但在自定义了这个按钮后(通过设self.navigationItem.leftBarButtonItem自定义),切换视图时按钮没有了动画。
最初解决方法
在每个viewController的viewWillAppear和viewDisappear方法上手动让按钮左右动。由于每个视图出现/消失的方向都有左/右两种,在这里难以判断,需要各种变量辅助,实现十分恶心,中间需要新加view时逻辑还要重新修改,被折腾。
最终解决方法
继承UINavigationController,重写pushViewController和popViewController方法,在这两个方法里面获取NavigationController里的view栈,因为push和pop总是操作最前面的View,所以可以从栈里知道哪两个view是要做动画的。调用这些view相应的方法使他们让自己的按钮动。这些方法可以写在UIViewController的扩展里,不用修改每一个viewController。
换言之,把下面的代码加入项目里,把项目里的UINavigationController换成下面的类,那些自定义的返回按钮就会自动做动画了。
代码
https://github.com/bang590/iOSPlayground/tree/master/NavigationButtonAnimate
//.h
#import <Foundation/Foundation.h>
@interface MainNavigationController : UINavigationController {
}
@end
//.m
#import "MainNavigationController.h"
@implementation UIViewController (UINavigationButtonAnimate)
- (void) viewAppearFromLeft
{
[self.navigationItem.leftBarButtonItem.customView setTransform:CGAffineTransformMakeTranslation(-60, 0)];
[UIView beginAnimations:@"viewAppearFromLeft" context:nil];
[UIView setAnimationDuration:0.3];
[self.navigationItem.leftBarButtonItem.customView setAlpha:1.0];
[self.navigationItem.leftBarButtonItem.customView setTransform:CGAffineTransformMakeTranslation(0, 0)];
[UIView commitAnimations];
}
- (void) viewAppearFromRight
{
[self.navigationItem.leftBarButtonItem.customView setTransform:CGAffineTransformMakeTranslation(60, 0)];
[UIView beginAnimations:@"viewAppearFromRight" context:nil];
[UIView setAnimationDuration:0.3];
[self.navigationItem.leftBarButtonItem.customView setAlpha:1.0];
[self.navigationItem.leftBarButtonItem.customView setTransform:CGAffineTransformMakeTranslation(0, 0)];
[UIView commitAnimations];
}
- (void) viewDisappearFromLeft
{
[UIView beginAnimations:@"viewDisappearFromLeft" context:nil];
[self.navigationItem.leftBarButtonItem.customView setTransform:CGAffineTransformMakeTranslation(60, 0)];
[UIView setAnimationDuration:0.3];
[self.navigationItem.leftBarButtonItem.customView setAlpha:0];
[UIView commitAnimations];
}
- (void) viewDisappearFromRight
{
[UIView beginAnimations:@"viewDisappearFromRight" context:nil];
[self.navigationItem.leftBarButtonItem.customView setTransform:CGAffineTransformMakeTranslation(-60, 0)];
[UIView setAnimationDuration:0.3];
[self.navigationItem.leftBarButtonItem.customView setAlpha:0];
[UIView commitAnimations];
}
@end
@implementation MainNavigationController
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
if (animated) {
UIViewController *popController = [self.viewControllers lastObject];
UIViewController *pushController = [self.viewControllers objectAtIndex:self.viewControllers.count - 2];
[popController viewDisappearFromLeft];
[pushController viewAppearFromLeft];
}
return [super popViewControllerAnimated:animated];
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (animated) {
UIViewController *popController = [self.viewControllers lastObject];
UIViewController *pushController = viewController;
[popController viewDisappearFromRight];
[pushController viewAppearFromRight];
}
[super pushViewController:viewController animated:animated];
}
@end