注意:当前控制器是:UINavigationController,是tabBar下所有控制器下统一创建的Navigation控制器
问题一:
- 设置leftBarButtonItem和rightBarButtonItem后,会覆盖系统的返回按钮,失去了滑动返回的手势功能。
解决方案:
//记录系统的代理属性
self.popDelegate = self.interactivePopGestureRecognizer.delegate;
//滑动返回功能
self.interactivePopGestureRecognizer.delegate = nil;
self.interactivePopGestureRecognizer是系统的滑动手势(可以打印出一些想要的信息)
- 还需要在以下代理方法(完全展示完调用)中恢复系统代理,系统的方法不能随意改变,不然会有新的bug
#pragma mark - 导航控制器的代理方法
// 完全展示完后调用
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
// 如果展示的控制器是根控制器,就还原pop手势代理
if (viewController == [self.viewControllers firstObject]) {
self.interactivePopGestureRecognizer.delegate = self.popDelegate;
}
}
新需求:
- 系统的滑动手势只有在旁边才有效,需要在更大范围有效果
打印系统的手势:
NSLog(@"%@",self.interactivePopGestureRecognizer);
<UIScreenEdgePanGestureRecognizer: 0x7f9c22148dd0; state = Possible; delaysTouchesBegan = YES; view = <UILayoutContainerView 0x7f9c2213db80>; target= <(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7f9c22148850>)>>
系统滑动手势类型:UIScreenEdgePanGestureRecognizer
target:_UINavigationInteractiveTransition
action:handleNavigationTransition:
查看过程
- 取出系统的手势对象
UIScreenEdgePanGestureRecognizer *ges = self.interactivePopGestureRecognizer;
NSLog(@"%ld",ges.edges);
- 打印唯一的edges属性 == 2
- 查看系统的 UIRectEdge edges 结构体所包含的值;
typedef NS_OPTIONS(NSUInteger, UIRectEdge) {
UIRectEdgeNone = 0,
UIRectEdgeTop = 1 << 0,
UIRectEdgeLeft = 1 << 1,
UIRectEdgeBottom = 1 << 2,
UIRectEdgeRight = 1 << 3,
UIRectEdgeAll = UIRectEdgeTop | UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight
} NS_ENUM_AVAILABLE_IOS(7_0);
- 可以看到结果和UIRectEdgeLeft相匹配,已经固定死
解决方案:自定义手势
- 防止和系统的手势发生冲突
self.interactivePopGestureRecognizer.enabled = NO;
以下代码所干的事:
取出系统手势的target对象, 然后再取出某个对象里面的属性
- 1.KVC 前提条件:必须知道属性名
2.利用运行时机制
- 导入框架 #import
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:@selector(handleNavigationTransition:)];
或者
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self.interactivePopGestureRecognizer.delegate action:@selector(handleNavigationTransition:)];
[self.view addGestureRecognizer:pan];
新bug:和直接设置self.interactivePopGestureRecognizer.delegate = nil;所出现的bug一样,在根控制器右滑后,无法再点击left/right按钮
解决方案:
取消根控制器触发bug的右边滑动的手势
- 遵守UIGestureRecognizerDelegate协议
- 设置代理pan.delegate = self;
- 实现代理方法
#pragma mark - 手势代理方法
// 是否开始触发手势
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
// 判断下当前控制器是否是根控制器
return (self.topViewController != [self.viewControllers firstObject]);
}