多手势冲突
当两个手势绑定在不同的view上,当滑动两个View公共区域时,只能响应上面view的手势。
1.如何使两个手势都响应?
自定义一个手势以UIPanGestureRecognizer为例。使用UIGestureRecognizer的代理方法
代码
#import <UIKit/UIKit.h>
@interface GestureOne : UIPanGestureRecognizer<UIGestureRecognizerDelegate>
@end
#import "GestureOne.h"
@implementation GestureOne
- (instancetype)initWithTarget:(id)target action:(SEL)action{
self = [super initWithTarget:target action:action];
if (self) {
self.delegate = self;
}
return self;
}
//表示手势共存:gestureRecognizer 和 otherGestureRecognizer 是否可以共存 ,返回YES可以
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
return YES;
}
@end
2.如果要使一个手势优先级的优先级大于另一个手势的优先级?( 例如一个View中有scrollView,那么navigationController的popRecognizer和scrollView的手势造成冲突,只会优先响应popRecognizer)
三种解决方法
第一种和第二种类似,即实现UIGestureRecognizer的代理方法
//返回YES gestureRecognizer手势不识别 ,otherGestureRecognizer识别
//返回NO gestureRecognizer手势识别 ,otherGestureRecognizer不识别
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return NO;
}
//返回YES gestureRecognizer手势识别 ,otherGestureRecognizer不识别
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
第三种,所有手势都有一个方法
- (void)requireGestureRecognizerToFail:(UIGestureRecognizer *)otherGestureRecognizer;
otherGestureRecognizer的优先级高于当前GestureRecognizer。
案例
该案例结合了事件传递、响应区域、手势冲突等
分析:scrollView的滑动方式是按照pagingEnabled的形式,且scrollView的width是小于屏幕宽度的。而且scrollView是存在多个手势,viewContoller也存在手势,势必会造成手势冲突。
-(void)learnScrollView{
// 超过view范围的不显示,由于scrollView超过view的返回会显示,所以让其为YES
self.view.clipsToBounds = YES;
CustomScrollView * scrollView = [[CustomScrollView alloc] initWithFrame:CGRectMake(20.f, 50.f, self.view.frame.size.width - 60, (self.view.frame.size.width - 80)*0.5)];
scrollView.contentSize = CGSizeMake((self.view.frame.size.width - 60)*5, (self.view.frame.size.width - 80)*0.5);
scrollView.clipsToBounds = NO;//超过scrollView范围也能显示
scrollView.pagingEnabled = YES;
for (int i = 0; i < 5; i++) {
UIImageView * imageView = [[UIImageView alloc] initWithFrame:CGRectMake(20 + (self.view.frame.size.width - 60) *i, 0, (self.view.frame.size.width - 80), (self.view.frame.size.width - 80)/2)];
imageView.image = [UIImage imageNamed:imageArr[i]];
[scrollView addSubview:imageView];
}
[self.view addSubview:scrollView];
//scrollView手势的优先级高于interactivePopGestureRecognizer
//防止滑动scrollView时退出Controller
[self.navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail:scrollView.panGestureRecognizer];
}
由于ScrollView的宽度是小于屏幕宽度的所以在滑动边缘的时候是不会成功,所以需要自定义ScrollView修改其点击范围
#import "CustomScrollView.h"
@implementation CustomScrollView
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event{
CGRect frame = self.bounds;
frame.origin.x -= 20;
frame.size.width = [UIScreen mainScreen].bounds.size.width;
if (CGRectContainsPoint(frame, point)) {
return YES;
}
return [super pointInside:point withEvent:event];
}
@end