1. 程式人生 > >手勢與控制元件事件衝突的解決方案

手勢與控制元件事件衝突的解決方案

在日常的開發中我們可能會遇到手勢與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點選方法的衝突問題,手勢與其他控制元件的衝突解決方法原理和這個相同,也是利用手勢的代理方法進行判斷,如果手勢執行的檢視不是需要的檢視就不讓其執行。