http://blog.cnbang.net/tech/1778/

 

问题

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

01. //.h
02. #import <Foundation/Foundation.h>
03. @interface MainNavigationController : UINavigationController {
04. }
05. @end
06.  
07. //.m
08. #import "MainNavigationController.h"
09. @implementation UIViewController (UINavigationButtonAnimate)
10. - (void) viewAppearFromLeft
11. {
12.     [self.navigationItem.leftBarButtonItem.customView setTransform:CGAffineTransformMakeTranslation(-60, 0)];
13.     [UIView beginAnimations:@"viewAppearFromLeft" context:nil];
14.     [UIView setAnimationDuration:0.3];
15.     [self.navigationItem.leftBarButtonItem.customView setAlpha:1.0];
16.     [self.navigationItem.leftBarButtonItem.customView setTransform:CGAffineTransformMakeTranslation(0, 0)];
17.     [UIView commitAnimations];
18. }
19. - (void) viewAppearFromRight
20. {
21.     [self.navigationItem.leftBarButtonItem.customView setTransform:CGAffineTransformMakeTranslation(60, 0)];
22.     [UIView beginAnimations:@"viewAppearFromRight" context:nil];
23.     [UIView setAnimationDuration:0.3];
24.     [self.navigationItem.leftBarButtonItem.customView setAlpha:1.0];
25.     [self.navigationItem.leftBarButtonItem.customView setTransform:CGAffineTransformMakeTranslation(0, 0)];
26.     [UIView commitAnimations];
27. }
28. - (void) viewDisappearFromLeft
29. {
30.     [UIView beginAnimations:@"viewDisappearFromLeft" context:nil];
31.     [self.navigationItem.leftBarButtonItem.customView setTransform:CGAffineTransformMakeTranslation(60, 0)];
32.     [UIView setAnimationDuration:0.3];
33.     [self.navigationItem.leftBarButtonItem.customView setAlpha:0];
34.     [UIView commitAnimations];
35. }
36. - (void) viewDisappearFromRight
37. {
38.     [UIView beginAnimations:@"viewDisappearFromRight" context:nil];
39.     [self.navigationItem.leftBarButtonItem.customView setTransform:CGAffineTransformMakeTranslation(-60, 0)];
40.     [UIView setAnimationDuration:0.3];
41.     [self.navigationItem.leftBarButtonItem.customView setAlpha:0];
42.     [UIView commitAnimations];
43. }
44. @end
45.  
46. @implementation MainNavigationController
47. - (UIViewController *)popViewControllerAnimated:(BOOL)animated
48. {
49.     if (animated) {
50.         UIViewController *popController = [self.viewControllers lastObject];
51.         UIViewController *pushController = [self.viewControllers objectAtIndex:self.viewControllers.count - 2];
52.         [popController viewDisappearFromLeft];
53.         [pushController viewAppearFromLeft];
54.     }
55.     return [super popViewControllerAnimated:animated];
56. }
57. - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
58. {
59.     if (animated) {
60.         UIViewController *popController = [self.viewControllers lastObject];
61.         UIViewController *pushController = viewController;
62.         [popController viewDisappearFromRight];
63.         [pushController viewAppearFromRight];
64.     }
65.     [super pushViewController:viewController animated:animated];
66. }
67. @end