iOS:导航控制器侧滑出栈实现

介绍:在iOS中,导航控制器UINavigationController是默认实现左侧边缘侧滑手势出栈的,但是如果当开发者对导航控制器子控制实现自定义leftBaButtonItem时,这个侧滑功能就会失去效果,此时就需要我们在自定义的NavigationController中手动代码去实现了。有的时候为了提高用户体验,会试着进行全屏的侧滑返回,现在这个技术已经普遍应用到app中。下面就来介绍边缘侧滑和全屏侧滑返回。。。。。

 

第一种方式:实现左侧边缘侧滑返回(系统自带的边缘侧滑,安全可靠)

iOS:导航控制器侧滑出栈实现
//
//  KJNavgationController.m
//
//  Created by mac on 16/2/22.
//  Copyright © 2016年 mac. All rights reserved.
//

#import "KJNavgationController.h"

@interface KJNavgationController ()<UIGestureRecognizerDelegate,UINavigationControllerDelegate>

@end

@implementation KJNavgationController
-(void)viewDidLoad{ [super viewDidLoad]; __weak KJNavgationController *weakSelf = self; if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) { self.interactivePopGestureRecognizer.delegate = weakSelf; self.delegate = weakSelf; } } - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated { //控制器入栈过程中禁用手势识别 if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) self.interactivePopGestureRecognizer.enabled = NO; [super pushViewController:viewController animated:animated]; } #pragma mark UINavigationControllerDelegate - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animate { //控制器入栈之后,启用手势识别 if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)]) self.interactivePopGestureRecognizer.enabled = YES; } - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { if ([self.childViewControllers count] == 1) { return NO; } return YES; } - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return YES; } //运行试一试,发现了新问题,手指在滑动的时候,被 pop 的 ViewController 中的 UIScrollView 会跟着一起滚动,这个效果看起来就很怪(知乎日报现在就是这样的效果),而且也不是原始的滑动返回应有的效果,那么就让我们继续用代码来解决吧 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer { return [gestureRecognizer isKindOfClass:UIScreenEdgePanGestureRecognizer.class]; } @end
iOS:导航控制器侧滑出栈实现

优点:实现简单,导航控制器中对全体viewController的侧滑功能可控,系统API绝对安全可靠,无手势冲突

缺点:侧滑范围局限于左侧

适用需求:只需左侧小范围触发侧滑时的首选实现方案。

 

 

第二种方式:实现全屏侧滑返回(并不完善的全屏侧滑)

iOS:导航控制器侧滑出栈实现
//
//  KJNavgationController.m
//
//  Created by mac on 16/2/22.
//  Copyright © 2016年 mac. All rights reserved.
//

#import "KJNavgationController.h"

@interface KJNavgationController ()<UIGestureRecognizerDelegate>

@end

@implementation KJNavgationController

-(void)viewDidLoad{
    [super viewDidLoad];
    
    // 获取系统自带滑动手势的target对象
    id target = self.interactivePopGestureRecognizer.delegate;
    
    // 创建全屏滑动手势,调用系统自带滑动手势的target的action方法
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector(handleNavigationTransition:)];
    
    // 设置手势代理,拦截手势触发
    pan.delegate = self;
    
    // 给导航控制器的view添加全屏滑动手势
    [self.view addGestureRecognizer:pan];
    
    // 禁止使用系统自带的滑动手势
    self.interactivePopGestureRecognizer.enabled = NO;
    
}

// 什么时候调用:每次触发手势之前都会询问下代理,是否触发。 // 作用:拦截手势触发 - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { // 注意:只有非根控制器才有滑动返回功能,根控制器没有。 // 判断导航控制器是否只有一个子控制器,如果只有一个子控制器,肯定是根控制器 if (self.childViewControllers.count == 1) { // 表示用户在根控制器界面,就不需要触发滑动手势, return NO; } return YES; } @end
iOS:导航控制器侧滑出栈实现

优点:最简洁的全屏侧滑实现,导航控制器中对全体viewController的侧滑功能可控

缺点:从右边往左边划动也能触发侧滑操作,有手势冲突,并不完美。且调用官方私有API

另外:正是缺点的所在,和Cell的侧滑删除手势也是有冲突的,也就是说,免不了需要解决手势的冲突。

适用需求:最好不用,毕竟缺点明显。(不过这个实现思路,确实值得称赞!)

 

 

第三种方式:(集成最简单、功能最全面):

链接地址下载DEMO,具体详情见github:https://github.com/forkingdog/FDFullscreenPopGesture

iOS:导航控制器侧滑出栈实现
使用截图
iOS:导航控制器侧滑出栈实现    iOS:导航控制器侧滑出栈实现

优点:最全面的全屏侧滑实现,集成超简单,全体viewController的侧滑功能可控,不过得在ViewController内部去控制,稍微麻烦一点;另外,百度知道团队在维护该DEMO,功能会越来越完善,花样更多。

缺点:调用官方私有API(不过已有上线作品,不影响上线,缺点可以忽略!)

适用需求:目前最好的全屏侧滑实现方案。

 

第四种方式:创建swipe扫动手势,实现全屏侧滑返回

iOS:导航控制器侧滑出栈实现
- (void)viewDidLoad
{
    [super viewDidLoad];
     
    // 添加右滑手势
    [self addSwipeRecognizer];
}
 
#pragma mark 添加右滑手势
- (void)addSwipeRecognizer
{
    // 初始化手势并添加执行方法
    UISwipeGestureRecognizer *swipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(return)];
     
    // 手势方向
    swipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
     
    // 响应的手指数
    swipeRecognizer.numberOfTouchesRequired = 1;
     
    // 添加手势
    [[self view] addGestureRecognizer:swipeRecognizer];
}
 
#pragma mark 返回上一级
- (void)return
{
    // 最低控制器无需返回
    if (self.viewControllers.count <= 1) return;
     
    // pop返回上一级
    [self popToRootViewControllerAnimated:YES];
}


//若在控制器之间跳转时需要做一些事情,可在自定义的控制器里添加下面两个方法
#pragma mark push方法
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    // do something you want
    ...
    [super pushViewController:viewController animated:animated];
}
 
#pragma mark pop方法
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
    // 比如停止网络请求
    ...
     
    return [super popViewControllerAnimated:animated];
}
        
iOS:导航控制器侧滑出栈实现

优点:用户可以自定义扫动侧滑,没有手势冲突,虽使用官方私有API,但是安全。

缺点:侧滑速度太快,不好控制器,不能中途停止侧滑。

适用需求:根据个人需要决定。

 

 

参看链接:

http://www.cocoachina.com/ios/20150811/12897.html

http://www.jianshu.com/p/349636eb3fca

http://www.jianshu.com/p/f83acf1d337b

http://my.oschina.net/cobish/blog/225260

程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式!
本文转自当天真遇到现实博客园博客,原文链接:http://www.cnblogs.com/XYQ-208910/p/5430068.html,如需转载请自行联系原作者
上一篇:linux交换分区 free dd 链接文件 压缩工具 归档工具


下一篇:Windows Embedded CE链接RNDIS的奇怪问题