感谢前人的无私奉献.  简书原文 ,  优化有bar,无bar的切换

前言

苹果在IOS7以后给导航控制器增加了一个Pop的手势,只要手指在屏幕边缘滑动,当前的控制器的视图就会跟随你的手指移动,当用户松手后,系统会判断手指拖动出来的大小来决定是否要执行控制器的Pop操作。

这个操作的想法非常好,但是系统给我们规定的范围必须是屏幕左侧边缘才可以触发,这样实际使用过程中对于有些产品会产生不便,于是有些app就采取整个屏幕都响应这个手势并且pop动画还是用系统原生的,这样操作起来确实方便好多。

推荐使用:Runtime+KVC

为了方便大家阅读下面的代码,我们需要先了解系统的这个手势。

前面我们了解到,这个手势属于UINavigationController,我们就跳到它的头文件里看看能不能找到线索。这个思路是正确的,确实有一个手势叫做interactivePopGestureRecognizer。属性为readonly,就是说我们不能给他换成自定义的手势,但是可以设置enable=NO。ok,既然找到了它,就打印一下看看它到底是一个什么手势。

通过log,我们看到他属于UIScreenEdgePanGestureRecognizer这个类(之前我是没有用到过),它继承自UIPanGestureRecognizer,出现在IOS7以后,是专门处理在屏幕边缘触发的手势类型,并且只有一个属性叫edges,用来设置它的触发边缘(上、下、左、右、全部)。

我们继续看它的log。控制台除了打印了它的类,还打印了它的触发target:_UINavigationInteractiveTransition(这是一个私有类,看来是专门用来做导航控制器交互动画的),和action:handleNavigationTransition(这是它的一个私有方法),我们要做的就是新建一个UIPanGestureRecognizer,让它的触发和系统的这个手势相同,这就需要利用runtime获取系统手势的target和action。

那么如何获取这个target呢?一开始我用kvc想直接获取这个手势的target,程序崩溃了,原来它根本没有这样一个属性。所以我能想到的是,先利用runtime遍历它的所有成员变量,看看系统是怎么存储这个属性的,

通过log我们可以看到,UIGestureRecognizer有一个叫_targets的属性,它的类型为NSMutableArray。

它是用数组来存储每一个target-action,所以可以动态的增加手势触发对象。那么又是什么存储每一个target-action呢?为了了解这个我们拿到这个属性的名字"_targets"通过kvc获取它,接着打印出来。

可以看到,由于系统重写了它的description方法,所以我们没办法通过打印获取这个对象是什么类型。既然不能打印,那么我们就用断点调试,来看它的真实类型,

我们看到,原来每一个target-action是用UIGestureRecognizerTarget这样一个类来存储的,它也是一个私有类。
苹果把许多的类做私有化也是有原因所在,其实在平时我们拿到这个类也是没有用的,他们的目的之一是避免对开发者公开无用的类,影响了封装性。所以在类的设计上,还是要向苹果学习。

下面直接看代码。

我们在控制器的ViewDidLoad加上这段代码,并且它只需要执行一次。

优化

这个demo我会提供给大家,下面简单说下程序的优化思路。

  • 优化点一:对于方案一,其实不应该把导航控制器的代理方法以及手势处理的方法交给视图控制器,因为这段代码不是属于某一个视图控制器,而是全局的导航控制器,所以我们应该参考苹果的设计思想:新建一个专门管理交互过程的对象,这个类我们叫做NavigationInteractiveTransition。

  • 优化点二:再来看之前的ViewDidLoad中只执行一次的代码,其实写在这里也不够妥当,同样的,这段代码也不属于某一个Controller,优化方案是新建一个导航控制器,在这个导航控制器的viewDidLoad中写上这些代码,这样也并不需要dispatch once。

  • 优化点三:由于我们自定义的手势是加在一个私有view上,这个view是一个全局的,所以当这个控制器为根控制器时,我们的手势还是在起作用,这就相当于对根控制器做了pop操作,这会出现一个错误nested pop animation can result in corrupted navigation bar。导致这个错误的原因还有一个,如果我们pop的动画正在执行,再去触发一次手势,会导致导航控制器和导航条的动画混乱。为了避免问题出现我们需要成为手势的代理,判断当前控制器是否为根控制器并且pop或者push动画是否在执行(这个变量是私有的,需要用kvc来获取)。

    经过最后的优化,视图控制器可以什么都不写,想使用这个效果,只要使用我们自定义的导航控制器就可以了,这样的好处是手势动画与控制器完全解耦,并且不用给每一个控制器都addGesture。


给大家推荐一个仓库https://github.com/nst/iOS-Runtime-Headers,这个仓库可以调取苹果的所有私有方法头文件,相当强大。

最后放上这个demo的地址:https://github.com/zys456465111/CustomPopAnimation(使用时,切换工程的scheme就能切换不同方案。对于方案二,只需要导航控制器的类就可以了。)

pod 'FDFullscreenPopGesture'

还发现了一个问题, 比如前一个页面是没有NavigationBar , 后一个页面有NavigationBar , 最好在前一个页面通过这种方式设置导航栏隐藏,如果直接使用     self.navigationController.navigationBarHidden = YES ;  没有设置动画的, 通过手势pop回来的时候,导航栏的位置是有很强的割裂感,嗯,就是很丑.

- (void)viewWillAppear:(BOOL)animated {[super viewWillAppear:animated];[self.navigationController setNavigationBarHidden:YES animated:animated];
}

ios 全屏返回手势相关推荐

  1. iOS 全屏侧滑手势/UIScrollView/UISlider间滑动手势冲突

    七夕节福利 效果预览 一.前期准备 有一个支持全屏侧滑返回的视图控制器ViewController,ViewController.view上有一个UIScrollView,UIScrollView上有 ...

  2. iOS 全屏侧滑/UIScrollView/UISlider间滑动冲突

    代码地址如下: http://www.demodashi.com/demo/13848.html 效果预览 一.前期准备 有一个支持全屏侧滑返回的视图控制器ViewController,ViewCon ...

  3. 【转】iOS右滑返回手势全解和最佳实施方案

    序言 在ios7以后,苹果推出了手势滑动返回功能,也就是从屏幕左侧向右滑动可返回上一个界面.大大提高了APP在大屏手机和iPad上的操作体验,场景切换更加流畅.做右滑返回手势配置时,可能会遇到的 问题 ...

  4. iOS 禁用侧滑返回手势要点整理

    项目中可能某些页面返回按钮需要自定义,然后在点击返回按钮时做出某些判断,或者直接弹出到根控制器,这时候需要禁用侧滑返回手势,防止它不走判断的代码直接返回上个界面. 网上找了些资料,大致方法有两种,但要 ...

  5. android 布局防抖动,Android全屏返回布局抖动问题

    在api19以后actvityA切到actvityB ,如果B是全屏的,A是非全屏的,这个时候切换回A会有一个状态栏出现的动画,随着状态栏出现动画我们的布局会出现一个从上往下的抖动. 在Actvity ...

  6. iOS 禁用侧滑返回手势

    在页面的生命周期设置如下代码 - (void)viewDidAppear:(BOOL)animated{[super viewDidAppear:YES];// 禁用返回手势if ([self.nav ...

  7. [搬运] iOS 7 侧滑返回手势使用和错误集

    原文:http://blog.sina.com.cn/s/blog_65c178a80102v0f4.html 前言: ios7开始 苹果增加了页面 右滑返回的效果:具体的是以UINavigation ...

  8. IOS 自定义 滑动返回 手势

    /** 只需要在你自定义的导航控制器中,改成如下代码即可,自定义手势返回 */ #define KEY_WINDOW [[UIApplication sharedApplication] keyWin ...

  9. iOS 一个丝滑的全屏滑动返回手势

    原文链接:http://blog.sunnyxx.com/2015/06/07/fullscreen-pop-gesture/ 全屏返回手势 自 iOS7 之后,Apple 增加了屏幕边缘右划返回交互 ...

最新文章

  1. C++中一些类和数据结构的大小的总结
  2. 新年新气象,2008年是我创业关键的一年!
  3. FastJSON的依赖
  4. 计算机 运行命令,教你电脑运行命令
  5. Android 网络通信架构学习
  6. ajax请求可以延时吗,延时校验AJAX请求
  7. 打印服务器打印文件,通过打印服务器远程打印文件
  8. 12009.IMU惯导传感器
  9. [leetcode] 题型整理之动态规划
  10. PHP 5.2、5.3、5.4、5.5、5.6 对比以及功能详解
  11. 用Python写的简易PDF阅读器
  12. 论文阅读 - Fame for sale: efficient detection of fake Twitter followers - Cresci - 2015数据集介绍
  13. 2015陈奕迅another eason‘s life演唱会歌单
  14. java 文件移动_java 文件移动
  15. 20230327 作业
  16. BZOJ1057: [ZJOI2007]棋盘制作
  17. 在UTF-8下写字库
  18. 【女黑客看《流浪地球2》是什么体验】
  19. linux有读EC RAM的工具吗,Shell下的ITE EC Tools
  20. javacv-音视频和图像处理

热门文章

  1. 取模(余)%运算详解
  2. 如何使用idea生成Doc文档
  3. 好嗨哟!OneOS 图形组件显示自己喜欢的图片
  4. SQL零基础入门学习(十四)
  5. AndroidStudio|读取SD卡中的sqlite数据
  6. 万字长文讲透AI艺术:缘起、意义和未来(下篇)
  7. 元宵快乐!!!! 自己做的贺卡。。 :)
  8. 中医学:—种基于隐喻认知的语言
  9. 电脑数据没有了怎么恢复?笔记本电脑数据丢失怎样恢复
  10. 生日快乐网页模板(HTML5+CSS3+JS)