问题

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​