iOS:导航控制器侧滑出栈实现
介绍:在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:导航控制器侧滑出栈实现的更多相关文章
- 关于ios导航控制器的知识总结
关于ios导航控制器的知识总结 添加了导航控制器后: 1.一个导航控制器会有一个顶部导航栏navigationbar和一个底部工具栏toolbar,它们是导航控制器navC的属性.且导航栏默认是不隐藏 ...
- iOS 导航控制器返回栈中的某一控制器
#import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDelegate> @pr ...
- iOS导航控制器常用函数与navigationBar常用属性
导航控制器常用函数触发时机 当视图控制器的View将要出现时触发 - (void)viewWillAppear:(BOOL)animated 当视图控制器的View已经出现时触发 - (void)vi ...
- IOS 导航控制器基本使用(UINavigationController代码创建方式)
● UINavigationController的使用步骤 ➢ 初始化UINavigationController ➢ 设置UIWindow的rootViewController为UINavigati ...
- 关于iOS导航控制器隐藏和显示会出现返回键失效,导航栏标题动画异常
最近做的demo bug出现了,我觉得这个bug出现得很经典所以贴出来给大家看看, bug演示就是:点击返回键失效出现如下gif图演示的内容 为啥会出现如此奇葩的bug,系统的返回键居然失效了,尴尬 ...
- iOS - 导航控制器
1.导航控制器 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.bac ...
- iOS 导航控制器如何随意push和pop 想要在 A push B 后, B 在push 到 D ,然后从 D pop 到 C ,在从 C pop 的A
这里主要是对导航控制器的viewControllerss这个数组进行操作,因为push操作和pop操作都是根据这个数据去切换控制器或者在这个数组里增加控制器的,所以只要改变这个子控制器数据就能自定义切 ...
- IOS开发UI篇—导航控制器属性和基本使用
IOS开发UI篇—导航控制器属性和基本使用 一.导航控制器的一些属性和基本使用 1.把子控制器添加到导航控制器中的四种方法 (1) 1.创建一个导航控制器 UINavigationController ...
- iOS开发——实用技术OC篇&8行代码教你搞定导航控制器全屏滑动返回效果
8行代码教你搞定导航控制器全屏滑动返回效果 前言 如果自定了导航控制器的自控制器的leftBarButtonItem,可能会引发边缘滑动pop效果的失灵,是由于 self.interactivePop ...
随机推荐
- golang-指针,函数,map
指针 普通类型变量存的就是值,也叫值类型.指针类型存的是地址,即指针的值是一个变量的地址.一个指针只是值所保存的位置,不是所有的值都有地址,但是所有的变量都有.使用指针可以在无需知道变量名字的情况下, ...
- phpcms v9表单向导添加验证码
要做留言板的功能,故用添加表单,想要在提交留言前加一个验证码的功能.网上的教程比较混乱,于是亲自实验了下,步骤如下: 首先是调用表单的页面加入验证码.表单js调用模版默认的是 \phpcms\temp ...
- Python安装scikit-learn包
我先是按照网上说的下载了个setuptools,然后直接用这个工具去安装,可是安装scikit-learn包的时候确老是有错误,也不知道错误是啥,所以就不用setuptools来安装了. 我直接下载了 ...
- 解决Tomcat因Redis加载慢而启动失败的问题
StartTomcat.py import subprocess as t import time, os, requests, sys WEB_IP = '127.0.0.1:8080' # WEB ...
- sizeof(类)
类的大小是什么?确切的说,类只是一个类型定义,它是没有大小可言的. 用sizeof运算符对一个类型名操作,得到的是具有该类型实体的大小.首先:我们要知道什么是类的实例化,所谓类的实例化就是在内存中分配 ...
- jquery中的jsonp和js中的jsonp还有配合php实现的jsonp。
最近在做一个自己的网站,才知道一个前端需要学习的东西到底有多少. 来吧~步入正题,我的网站空间很小.所以在资源上,就有点吼不住了.跨域拿数据肯定是不可避免的了. 一.原生js: 我们知道他的原理,就是 ...
- SpringMVC完成文件上传的基本步骤
1.修改form表单的提交方式 2.将文件存入磁盘 3.配置视图解析器 1).前端文件 --需要在form表单中添加 enctype="multipart/form-data"属性 ...
- HDU 6186 CS Course【前后缀位运算枚举/线段树】
[前后缀枚举] #include<cstdio> #include<string> #include<cstdlib> #include<cmath> ...
- AndroidManifest.xml文件详解(uses-feature)
http://blog.csdn.net/think_soft/article/details/7596796 语法(SYNTAX): <uses-featureandroid:name=&qu ...
- SystemProperties cannot be resolved错误
单独用eclipse打开一个工程,出现SystemProperties.get()会出现SystemProperties cannot be resolved.错误 1. 引用SystemProper ...