侧滑返回的效果
效果图从iOS7开始,系统为UINavigationController添加 interactivePopGestureRecognizer属性,这个属性就是系统提供的右滑返回动画,我们可以通过滑动左边边缘实现pop效果。我们可以通过,如上图所示。self.navigationController.interactivePopGestureRecognizer.enabled = NO关闭系统默认的边缘返回动画。
缺点:
只能实现边缘拖动,如果从视图除左边边缘以外的部分没有效果。如果push到其他界面,如果重写的leftBarButtonItem就失效了。如果解决上面两个问题,我们需要重新实现动画效果。系统只提供了边缘手势,而没有提供在任何地方都可以右滑返回的动画,所以这个需要我们自己创建一个UIPanGestureRecognizer手势。文章后面会具体讲解如何实现。 那么,还有一个问题,也就是如果重写的leftBarButtonItem系统的边缘手势就失效了,这个该如何解决呢?其实也非常简单,我们只需要在重写leftBarButtonItem的界面加上下面的代码即可:
self.navigationController.interactivePopGestureRecognizer.delegate = self; #pragma mark - UIGestureRecognizerDelegate - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { //导航的rootViewController关闭右滑返回功能 if (self.navigationController.viewControllers.count <= 1) { return NO; } return YES; }上面代码可以看出:重新设置了interactivePopGestureRecognizer对象的代理,interactivePopGestureRecognizer 其实也是UIGestureRecognizer的一个子类,然后重写gestureRecognizerShouldBegin:方法,判断导航的根控制器不需要侧滑返回的功能。github下载地址。
提示:
self.navigationItem.leftBarButtonItem = customLeftBarButtonItem; //右滑返回失效 self.navigationItem.backBarButtonItem = customLeftBarButtonItem; //不影响右滑返回那么,如果实现一个自定义右滑返回呢?代码很简单。 1.自定义一个所有控制器的父类,比如DLBaseViewController, 然后在DLBaseViewController的viewDidLoad方法添加下面代码:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. //1.获取系统interactivePopGestureRecognizer对象的target对象 id target = self.navigationController.interactivePopGestureRecognizer.delegate; //2.创建滑动手势,taregt设置interactivePopGestureRecognizer的target,所以当界面滑动的时候就会自动调用target的action方法。 //handleNavigationTransition是私有类_UINavigationInteractiveTransition的方法,系统主要在这个方法里面实现动画的。 UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] init]; [pan addTarget:target action:NSSelectorFromString(@"handleNavigationTransition:")]; //3.设置代理 pan.delegate = self; //4.添加到导航控制器的视图上 [self.navigationController.view addGestureRecognizer:pan]; //5.禁用系统的滑动手势 self.navigationController.interactivePopGestureRecognizer.enabled = NO; } #pragma mark - 滑动开始会触发 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { //只有导航的根控制器不需要右滑的返回的功能。 if (self.navigationController.viewControllers.count <= 1) { return NO; } return YES; }下面我们的所有的类都继承DLBaseViewController即可。滑动界面的任何地方都可以右滑返回。运行效果图如下。Demo下载地址
效果图2.如果有TabbarController,上面的方法还可以用吗?我们创建一个TabbarController的工程,然后测试结果如下:
基于TabbarController注意: 上面进入第2页隐藏tabbar,是在storyboard选中TwoViewController,勾上Hide Bottom Bar on Push 如下图所示:
进入第2页隐藏tabbar3.一行代码搞定右滑返回功能。 上面我们把功能代码写到了父类里面,这样的坏处就是必须每个控制器都要继承同一个父类,所以比较麻烦。而且上面的代码每个控制器都需要执行一次,所以效率比较低。基于上面的缺点,然后用runtime的method swizzling强大技术封装了一个更简单的方法,一行代码就搞定了。详解demo
/* 开启右滑返回手势 注意: 1.一定要在appDelegate里面开启,并且在UINavigationController初始化之前,否则没有效果。 2.如果用的storyboard,直接在appDelegate类didFinishLaunchingWithOptions开启即可 */ [DLNavigationTransition enableNavigationTransitionWithPanGestureBack];注意:由于通过runtime在UINavigationController的viewDidLoad里面添加了手势代码,所以一定要在appDelegate里面开启,并且在UINavigationController初始化之前,否则没有效果。如果项目用的是storyboard,直接在appDelegate类的didFinishLaunchingWithOptions开启即可。