浅谈iOS右滑pop功能的实现

侧滑返回的效果

浅谈iOS右滑pop功能的实现_第1张图片
效果图

从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,
然后在DLBaseViewControllerviewDidLoad方法添加下面代码:

- (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下载地址

浅谈iOS右滑pop功能的实现_第2张图片
效果图

2.如果有TabbarController,上面的方法还可以用吗?我们创建一个TabbarController的工程,然后测试结果如下:

浅谈iOS右滑pop功能的实现_第3张图片
基于TabbarController

注意: 上面进入第2页隐藏tabbar,是在storyboard选中TwoViewController,勾上Hide Bottom Bar on Push
如下图所示:

浅谈iOS右滑pop功能的实现_第4张图片
进入第2页隐藏tabbar

3.一行代码搞定右滑返回功能。
上面我们把功能代码写到了父类里面,这样的坏处就是必须每个控制器都要继承同一个父类,所以比较麻烦。而且上面的代码每个控制器都需要执行一次,所以效率比较低。基于上面的缺点,然后用runtimemethod swizzling强大技术封装了一个更简单的方法,一行代码就搞定了。详解demo

/*
  开启右滑返回手势
  注意:
  1.一定要在appDelegate里面开启,并且在UINavigationController初始化之前,否则没有效果。
  2.如果用的storyboard,直接在appDelegate类didFinishLaunchingWithOptions开启即可
 */
 [DLNavigationTransition enableNavigationTransitionWithPanGestureBack];

注意:由于通过runtimeUINavigationControllerviewDidLoad里面添加了手势代码,所以一定要在appDelegate里面开启,并且在UINavigationController初始化之前,否则没有效果。如果项目用的是storyboard,直接在appDelegate类的didFinishLaunchingWithOptions开启即可。

你可能感兴趣的:(浅谈iOS右滑pop功能的实现)