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

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

//
// 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] == ) {
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

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

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

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

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

//
// 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 == ) {
// 表示用户在根控制器界面,就不需要触发滑动手势,
return NO;
}
return YES;
}
@end

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

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

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

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

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

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

使用截图
    

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

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

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

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

- (void)viewDidLoad
{
[super viewDidLoad]; // 添加右滑手势
[self addSwipeRecognizer];
} #pragma mark 添加右滑手势
- (void)addSwipeRecognizer
{
// 初始化手势并添加执行方法
UISwipeGestureRecognizer *swipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(return)]; // 手势方向
swipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight; // 响应的手指数
swipeRecognizer.numberOfTouchesRequired = ; // 添加手势
[[self view] addGestureRecognizer:swipeRecognizer];
} #pragma mark 返回上一级
- (void)return
{
// 最低控制器无需返回
if (self.viewControllers.count <= ) 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];
}

优点:用户可以自定义扫动侧滑,没有手势冲突,虽使用官方私有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

iOS:导航控制器侧滑出栈实现的更多相关文章

  1. 关于ios导航控制器的知识总结

    关于ios导航控制器的知识总结 添加了导航控制器后: 1.一个导航控制器会有一个顶部导航栏navigationbar和一个底部工具栏toolbar,它们是导航控制器navC的属性.且导航栏默认是不隐藏 ...

  2. iOS 导航控制器返回栈中的某一控制器

    #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @pr ...

  3. iOS导航控制器常用函数与navigationBar常用属性

    导航控制器常用函数触发时机 当视图控制器的View将要出现时触发 - (void)viewWillAppear:(BOOL)animated 当视图控制器的View已经出现时触发 - (void)vi ...

  4. IOS 导航控制器基本使用(UINavigationController代码创建方式)

    ● UINavigationController的使用步骤 ➢ 初始化UINavigationController ➢ 设置UIWindow的rootViewController为UINavigati ...

  5. 关于iOS导航控制器隐藏和显示会出现返回键失效,导航栏标题动画异常

    最近做的demo  bug出现了,我觉得这个bug出现得很经典所以贴出来给大家看看, bug演示就是:点击返回键失效出现如下gif图演示的内容 为啥会出现如此奇葩的bug,系统的返回键居然失效了,尴尬 ...

  6. iOS - 导航控制器

    1.导航控制器 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.bac ...

  7. iOS 导航控制器如何随意push和pop 想要在 A push B 后, B 在push 到 D ,然后从 D pop 到 C ,在从 C pop 的A

    这里主要是对导航控制器的viewControllerss这个数组进行操作,因为push操作和pop操作都是根据这个数据去切换控制器或者在这个数组里增加控制器的,所以只要改变这个子控制器数据就能自定义切 ...

  8. IOS开发UI篇—导航控制器属性和基本使用

    IOS开发UI篇—导航控制器属性和基本使用 一.导航控制器的一些属性和基本使用 1.把子控制器添加到导航控制器中的四种方法 (1) 1.创建一个导航控制器 UINavigationController ...

  9. iOS开发——实用技术OC篇&8行代码教你搞定导航控制器全屏滑动返回效果

    8行代码教你搞定导航控制器全屏滑动返回效果 前言 如果自定了导航控制器的自控制器的leftBarButtonItem,可能会引发边缘滑动pop效果的失灵,是由于 self.interactivePop ...

随机推荐

  1. Leetcode 之Length of Last Word(37)

    扫描每个WORD的长度并记录即可. int lengthOfLast(const char *s) { //扫描统计每个word的长度 ; while (*s) { if (*s++ != ' ')/ ...

  2. 算法入门系列1:k-means

    k-means是一种无监督学习算法,用于聚类. 下图(来自http://www.cnblogs.com/jerrylead/archive/2011/04/06/2006910.html)展示了k-m ...

  3. 讲IOC非常好的一篇文章--初步弄懂DI

    http://jinnianshilongnian.iteye.com/blog/1413846 http://jinnianshilongnian.iteye.com/blog/pdf 之后又看了类 ...

  4. hdu5731

    先求出不考虑分割线的n*m棋盘的覆盖方案数记为f[n][m] 然后枚举列分割线的状态(状压),计算此时不存在行分割线的方案数 求出这个我们就可以用容斥原理算出答案了 怎么算在列分割线确定的情况下,不存 ...

  5. AC日记——[USACO06FEB]奶牛零食Treats for the Cows 洛谷 P2858

    [USACO06FEB]奶牛零食Treats for the Cows 思路: 区间DP: 代码: #include <bits/stdc++.h> using namespace std ...

  6. Partial Views

    @Html.Partial("MyPartial")   @Html.Partial("MyStronglyTypedPartial", new [] {&qu ...

  7. LoadRunner中进程运行和线程运行区别

    LoadRunner中的进程与线程    1.进程与线程的区别: 进程和线程的区别是什么?进程和线程都是由操作系统所体会的程序运行的基本单元,系统利用该基本单元实现系统对应用的并发性.进程和线程的区别 ...

  8. OpenStack 安装数据库和rabbitmq消息队列 (三)

    一)安装配置数据库 1.1.安装包 # yum install mariadb mariadb-server python2-PyMySQL -y 1.2.配置数据库 # vim /etc/my.cn ...

  9. python版GetTickCount()

    time.clock() return the current processor time as a floating point number expressed in seconds. 即返回一 ...

  10. Project interpreter not specified(eclipse+pydev) (转)

    [小记] 最近因为想配置Android的开发环境,把原来的MyEclipse5.5删了,下载了最新的Eclipse3.7版本,因为之前在进行Python开 发,就下载了最新的Pydev2.4版本,安装 ...