导航控制器的2种滑动返回功能
2016-05-15 本文已影响531人
小小小阿博er
- 我们经常看到应用中有这样的效果(除了点击导航条上面的按钮pop到上一个页面外)
- 手指在屏幕最左边向右滑动就可以返回上一个页面
- 手指在屏幕任意地方向右就可以返回上一个页面(全屏滑动返回)
为什么需要自己设置滑动返回?
- 是的,从iOS7开始,系统自带的就有上述所说的第一种滑动返回效果,但是前提是我们不可以去覆盖系统自带的UIBarbuttonItem,但是很多情况下我们是需要自定义这个返回按钮的,这样系统自带的滑动返回功能就自动失效了
- OK,废话不多说,直接来效果了,先搞定系统自带的那种滑动返回效果
如何设置呢?
- UINavigationController.h文件里我们可以看到这样一个属性
UIGestureRecognizer *interactivePopGestureRecognizer
它就是导航控制器用来支持滑动返回的那个手势,手势内部有一个代理,这个代理会自动帮我们处理很多事情,当然包括了系统自带的滑动返回。所以我们如果自定义了返回按钮,这个代理就会不怎么听话了,系统自带的滑动返回就自动失效,但是这个时候我们又想使用这种功能,所以我们就想到了去怎么搞一搞这个手势的代理让它听话点呢- 首先,我们需要定义一个id类型的代理属性去记录一下系统的那个滑动返回的手势代理,以便接下来操作它
@property (nonatomic, strong) id popDelegate;
- 接下来,我们需要在控制器加载完毕的方法中将这个代理保存起来
self.popDelegate = self.interactivePopGestureRecognizer.delegate
- 然后就是问题的关键了,我们该如何去控制这个代理呢,让它什么时候帮我们做事去恢复这个滑动返回什么时候不要帮我们恢复滑动返回呢
这里首先需要说明一下的是,我们本身只需要把这个代理清空赋值为nil,其实就可以在我们自定义滑动返回按钮的情况下让它恢复滑动返回功能,但是直接这样操作的后果是:(这里举一个例子,就是从当前页面Apush到下一个页面B)然后你从B页面返回到A页面后,一旦你继续从屏幕左侧向右滑,你会发现A页面点击没有反应了,所以仅仅这样做肯定是不好的
所以核心就是重写导航控制器的push方法,在push方法中如果当前是非根控制器那么就将这个代理清空,而且必须要在调用父类的push操作之前将其清空哦
- 首先,我们需要定义一个id类型的代理属性去记录一下系统的那个滑动返回的手势代理,以便接下来操作它
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (self.viewControllers.count != 0) { // 非根控制器
// 清空代理后就有滑动返回功能
self.interactivePopGestureRecognizer.delegate = nil;
}
[super pushViewController:viewController animated:animated];
}
//清空之后什么时候还原呢,如果不还原,就会像刚刚说的那样,在根控制器页面一旦在左侧向右滑动了,页面就无法点击了
//在导航控制器完全pop到根控制器完成的时候还原就可以了,在以下方法还原就可以了
//导航控制器完全pop到根控制器完成这个操作导航控制器自己监听最合适,所以要遵守<UINavigationControllerDelegate>这个协议
//这个时候需要自己监听自己的事情,那么让导航控制器自己成为自己的代理
- (void)viewDidLoad {
[super viewDidLoad];
//用一个id值去记录这个代理,方便在其他方法中操作这个代理
self.popDelegate = self.interactivePopGestureRecognizer.delegate;
//自己成为自己的代理,监听完全pop到根控制器
self.delegate = self;
}
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
// 如果pop完成的时候展示的是根控制器,那么就还原返回手势代理
//这个方法中携带的viewController就是pop或者push完成后展示的那个控制器
if (viewController == [self.viewControllers firstObject]) {
self.interactivePopGestureRecognizer.delegate = self.popDelegate;
}
}
- ok啦,这样操作之后系统的那个滑动返回效果就可以在我们自定义返回按钮后生效了,关键地方就在我们需要在返回到根控制器的时候恢复这个代理,如果不是根控制器就清空这个代理
- 非常抱歉,本来打算2个滑动返回效果都描述一遍,但是由于时间关系,今天已经是周日凌晨一点多了,待我养精蓄锐之后再来呕心沥血(开个玩笑~~~)
- 下午会补上全屏滑动效果实现