手势与控件事件冲突的解决方案

在日常的开发中我们可能会遇到手势与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点击方法的冲突问题,手势与其他控件的冲突解决方法原理和这个相同,也是利用手势的代理方法进行判断,如果手势执行的视图不是需要的视图就不让其执行。

猜你喜欢

转载自blog.csdn.net/bluecat_1128/article/details/52824857
今日推荐