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 ...
随机推荐
- C#面向对象(OOP)入门—第二天—多态和继承(继承)
介绍: 第一天的内容主要是不同情形下的方法重载.这一部分则主要讲面向对象中继承的概念.首先用一个要点图形来定义继承. 继承 一个简单的例子: ClassA: class ClassA:ClassB { ...
- php的设计模式------工厂模式
1.工厂模式简介 属于创建型模式.定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行主要解决的问题:接口选择的问题. 2.分类 2.1 简单工厂模式 接口: ...
- java之基本数据类型与引用数据类型
基本数据类型 需要注意的是字符是基本数据类型,但是字符串不是基本数据类型. 引用数据类型 类.接口类型.数组类型.枚举类型.注解类型. (上面说的字符串String属于引用数据类型中“类”的范畴) 两 ...
- Django web框架之模板继承
模板继承 (extend) Django模版引擎中最强大也是最复杂的部分就是模版继承了.模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素,并且可以定义能够被子模版覆盖的 block ...
- 深入解析当下大热的前后端分离组件django-rest_framework系列三
三剑客之认证.权限与频率组件 认证组件 局部视图认证 在app01.service.auth.py: class Authentication(BaseAuthentication): def aut ...
- LeetCode Binary Tree PostorderTranversal
Problem Description Given a binary tree, return the postorder traversal of its nodes' values. For ex ...
- VS Code使用
VS Code使用了有一段时间了,感觉各方面表现蛮好的,当然主要还是基于electron开发的,(有源代码,想改啥就改啥,当然现在也没有改什么,没那么时间,也没有那么多精力),性能不错,其实中间主要还 ...
- React Native 0.56.1初始化项目运行出现错误(Module `AccessibilityInfo` does not exist in the Haste module map)
当使用react-native init myApp初始化项目时,出现以下错误 出现以上错误的原因是因为0.56.1版本初始化项目就有问题,请见 https://github.com/facebook ...
- jQuery筛选
1.filter筛选出与指定表达式匹配的元素集合 html: <p>Hello</p><p>Hello Again</p><p class=&qu ...
- BZOJ2654/COGS1764 [2012国家集训队]tree(陈立杰) [生成树,二分]
BZOJ传送门,COGS传送门 tree Description 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. Input 第一行V, ...