iOS导航栏--侧滑失效问题

iOS导航栏侧滑失效问题

关于iOS的导航栏, 想必各个iOS开发者都是经常要面对的问题.也是必须熟练掌握的一个技术点.

比较坑的有两方面.
  • 1.一方面是导航栏上的控件位置问题.
  • 2.一方面是导航栏的返回按钮自定义问题.

今天我主要分享一下自己对这个问题的解决方案的看法.首先我们先来看看iOS中如何设置返回按钮.

iOS中设置返回按钮有两种方式.
  • 一种是在上一级控制器配置.(配置backBarButtonItem)
  • 一种是在本控制器配置.(leftBarButtonItem)

前者只能配置文字或者图片.而不能用自定义的View去配置.苹果的官方文档有如下解释

When this navigation item is immediately below the top item in the stack, 
the navigation controller derives the back button for the navigation bar 
from this navigation item. When this property is nil, the navigation item 
uses the value in its title property to create an appropriate back button. If 
you want to specify a custom image or title for the back button, you can 
assign a custom bar button item (with your custom title or image) to this 
property instead. When configuring your bar button item, do not assign a 
custom view to it; the navigation item ignores custom views in the back 
bar button anyway.

当这个属性是nil的是否, 导航栏使用它的title属性创建一个返回按钮.如果你要为
返回按钮自定义一张图片或者文字, 你可以赋值文字或者图片给UIBarButtonItem
对象.但是对于自定义的View, 在backBarButtonItem中会被忽略.

后者可以很方便的自定义返回按钮.

当同时也存在一个致命的缺点, 就是用leftBarButtonItem自定义返回按钮后, 侧滑手势会失效.如下代码:

UIView *redView = [UIView new];
redView.width = redView.height = 100;
UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView: redView];
self.navigationItem.leftBarButtonItem = item;

具体原因:

这是为什么呢?从iOS7开始, 系统为UINavigationController, 提供了interactivePopGestureRecognizer手势, 用于右滑返回(pop).但是如果使用leftBarButtonItem属性自定义了返回按钮, 就会造成手势失效.要知道具体原因, 我们还要了解, interactivePopGetureRecognizer从手势触发到行为发生, 要经历以下过程.

Paste_Image.png

interactivePopGestureRecogizer还存在, 但没有起作用.是因为delegate里被阻断了没有调用target/action.或者是调用了, 但没有运行动画.
如果我们知道action的名字, 则可以添加一个自定义的滑动手势, 字节调用系统的action.但是API文档没有提供, 所以该action应该是一个私有的API.使用私有API会造成AppStore审核被拒绝, 所以这个思路也不可取.

那么, 我们就要自己实现滑动返回的动画action, 要么自己重写interfactivePopGestureRecognizer手势的delegate以让手势继续下去, 触发系统的action里面对应的动画.

实现方法:

自定义NavigationController, 遵守手势协议.
设置interactivePopGestureRecognizer手势的代理对象为自身(自定义的navigationController自身)

- (void)viewDidLoad { 
[super viewDidLoad];
self.interactivePopGestureRecognizer.delegate = self; 
}

让手势生效

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { 
  if (self.viewControllers.count <= 1 ) { 
      return NO; 
  } 
  return YES; 
}

// 允许同时响应多个手势
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer        
shouldRecognizeSimultaneouslyWithGestureRecognizer:
(UIGestureRecognizer *)otherGestureRecognizer { 
   return YES;
}

禁止响应手势的是否ViewController中scrollView跟着滚动

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer 
shouldBeRequiredToFailByGestureRecognizer:
(UIGestureRecognizer *)otherGestureRecognizer {    
return [gestureRecognizer isKindOfClass:
UIScreenEdgePanGestureRecognizer.class];
}

在push动画发生的时候, 禁止滑动手势, 因为push动作还没完成, 逻辑上是不允许这个是否进行滑动.重写pushViewController:XX方法.

self.interactivePopGestureRecognizer.enabled = NO;

在使用navigationController的viewController里面添加

- (void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated];     
    self.navigationController.interactivePopGestureRecognizer.enabled = YES;
 }

或者使导航控制器成为自身的代理, 监听Push完成后的ViewController

- (void)navigationController:(UINavigationController *)navigationController       
didShowViewController:(UIViewController *)viewController                    
animated:(BOOL)animate {    
//控制器入栈之后,启用手势识别    
  if ([self respondsToSelector:@selector(interactivePopGestureRecognizer)])        
      self.interactivePopGestureRecognizer.enabled = YES;
}

// 如果要这样做, 同时应该让该导航控制器成为自己的代理
// 在上面的viewDidLoad里添加如下一句代码
self.delegate = self

后续

如果你不想自己实现.这里有一个韩国开发者利用runtime技术写的框架, 解决了该问题.https://github.com/devxoul/SwipeBack.
.但是实际测试中, 发现该框架还有不足之处, 如有遇到使用该框架还是无效的, 可以参照上面的步骤进行更改, 自定义导航控制器.关于导航栏上的控件位置问题, 会在下一篇进行介绍.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,710评论 4 376
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,839评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,295评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,776评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,198评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,074评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,200评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,986评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,733评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,877评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,348评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,675评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,393评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,209评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,212评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,003评论 2 280

推荐阅读更多精彩内容