在日常的开发中我们可能会遇到手势与UI控件事件出现冲突造成监听事件混乱的情况,其实解决方案非常简单。在这里我用点击手势与UICollectionView的item点击事件作为案例对此方法做一下简单的介绍。比如有如下案例:
图中下边绿色的为UICollectionView,红色的控件为其中的item,现在想要实现点击UICollectionView回收键盘,而点击item出现弹窗。我的方法是给UICollectionView添加一个点击的手势,点击回收键盘,然后在UICollectionView的代理方法”- (void)collectionView:(UICollectionView )collectionView didSelectItemAtIndexPath:(NSIndexPath )indexPath”中添加item的点击弹窗,代码如下:
- (void)viewDidLoad {
[super viewDidLoad];
// 设置界面布局
[self configureUI];
}
// 界面布局
- (void)configureUI{
UITextField *textField = [[UITextField alloc]initWithFrame:CGRectMake(10, 30, [UIScreen mainScreen].bounds.size.width-20, 44)];
[self.view addSubview:textField];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.backgroundColor = [UIColor whiteColor];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(([UIScreen mainScreen].bounds.size.width - 80)/ 3, 80);
layout.minimumLineSpacing = 20;
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(textField.frame)+10, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height-CGRectGetMaxY(textField.frame)) collectionViewLayout:layout];
collectionView.delegate = self;
collectionView.dataSource = self;
collectionView.backgroundColor = [UIColor greenColor];
[self.view addSubview:collectionView];
[collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];
// 为collectionView添加手势,点击回收键盘
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(collectionViewClickAction)];
// 利用代理方法解决后边手势与item点击事件之间的冲突
tap.delegate = self;
[collectionView addGestureRecognizer:tap];
}
#pragma mark - UICollectionView的数据源及代理
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return 6;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
cell.backgroundColor = [UIColor redColor];
return cell;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(20, 20, 20, 20);
}
// 为了测试增加点击item弹窗的方法
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:@"测试弹窗" message:@"item被点击了" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alertView show];
}
#pragma mark - 手势相关
// 手势方法,点击回收键盘
- (void)collectionViewClickAction{
[self.view endEditing:YES];
}
但是按照上边代码执行之后会发现”- (void)collectionView:(UICollectionView )collectionView didSelectItemAtIndexPath:(NSIndexPath )indexPath”这个方法在点击item的时候不会执行,而且点击item依然会执行手势方法回收键盘,所以在这里要利用手势的代理方法进行判断,如果点击的视图是UICollectionView就执行手势,否则不执行手势,所以在上边的代码中增加如下方法
// 手势代理方法
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
// 判断如果点击的View是UICollectionView就可以执行手势方法,否则不执行
if ([touch.view isKindOfClass:[UICollectionView class]]) {
return YES;
}
return NO;
}
如此判断便很好的解决了点击手势与item点击方法的冲突问题,手势与其他控件的冲突解决方法原理和这个相同,也是利用手势的代理方法进行判断,如果手势执行的视图不是需要的视图就不让其执行。