解決右滑返回手勢和UIScrollView中的手勢沖突

項(xiàng)目中遇到一個(gè)頁面中是以一個(gè)scrollview橫向Tab展示兩個(gè)不同功能的顯示,譬如消息和公告功能,但是由于滑動(dòng)返回手勢和scrollview的滑動(dòng)返回手勢沖突了,導(dǎo)致頁面不再能夠滑動(dòng)返回。類似的還有圖片瀏覽功能也出現(xiàn)過。

iOS系統(tǒng)中,滑動(dòng)返回手勢,其實(shí)是一個(gè)UIPanGestureRecognizer,系統(tǒng)默認(rèn)的操作是只有滑動(dòng)屏幕的左邊的某個(gè)位置,UIPanGestureRecognizer才會(huì)起作用。UIScrollView的滑動(dòng)手勢也是UIPanGestureRecognizer。那在側(cè)邊滑動(dòng)時(shí),讓UIScrollView的不響應(yīng)事件就OK了嘛,首先想到了繼承UIScrollView 重寫下面的方法,讓滑動(dòng)側(cè)邊時(shí)scrollView不響應(yīng)事件,根據(jù)響應(yīng)者鏈,事件最終會(huì)傳遞給下方的滑動(dòng)手勢。

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event     {
      if (point.x < location.x) { // location.x為系統(tǒng)的某個(gè)點(diǎn)的x
          return nil;
      } else {
          return [super hitTest:point withEvent:event];
      }
}

但是,這樣有個(gè)問題,就是在一個(gè)頁面不同tab時(shí),也需要滑動(dòng)切換,滑動(dòng)返回。

由于scrollView的滑動(dòng)手勢攔截了事件,那我重寫scrollView中panGestureRecognizer的代理方法,讓它不攔截就好了嘛。于是繼承UIScrollView,重寫下面的方法。

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {

        if ([self panBack:gestureRecognizer]) {
             return YES;
        }
        return NO;

 }


- (BOOL)panBack:(UIGestureRecognizer *)gestureRecognizer {

    if (gestureRecognizer == self.panGestureRecognizer) {
          UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)gestureRecognizer;
          CGPoint point = [pan translationInView:self];
          UIGestureRecognizerState state = gestureRecognizer.state;
          if (UIGestureRecognizerStateBegan == state || UIGestureRecognizerStatePossible == state) {
              CGPoint location = [gestureRecognizer locationInView:self];
              if (point.x > 0 && location.x < “這個(gè)自己設(shè)定" && self.contentOffset.x <= 0) {
                   return YES;
              }
          }
     }
     return NO;

}

需要側(cè)邊滑動(dòng)時(shí) panBack 返回YES,這時(shí)候,我讓scrollView的手勢和頁面的滑動(dòng)返回手勢共存,scrollView不攔截手勢,那不就可以滑動(dòng)返回了嗎。好了,測試一下,可以滑動(dòng)返回,但是滑動(dòng)返回時(shí),為什么scrollView也跟著在滑動(dòng)呢,太影響美觀了,看來還需要另外的辦法,我又回到了第一種辦法時(shí)的想法,讓scrollView切換的時(shí)候相應(yīng)panGesture,滑動(dòng)返回的時(shí)候不響應(yīng),那重寫scrollView中的另外一個(gè)panGestureRecognizer的代理方法。

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {

    if ([self panBack:gestureRecognizer]) {
        return NO;
    }
    return YES;

}

第二種方法:

 -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer  
 {  
     // 首先判斷otherGestureRecognizer是不是系統(tǒng)pop手勢  
     if ([otherGestureRecognizer.view isKindOfClass:NSClassFromString(@"UILayoutContainerView")]) {  
         // 再判斷系統(tǒng)手勢的state是began還是fail,同時(shí)判斷scrollView的位置是不是正好在最左邊  
         if (otherGestureRecognizer.state == UIGestureRecognizerStateBegan && self.contentOffset.x == 0) {  
              return YES;  
         }  
     }  
  
     return NO;  
}  

以上的代碼都是在一個(gè)自定義的UIScrollView上的,重寫上面的方法即可。然后讓橫向滾動(dòng)的scrollView繼承這個(gè)自定義UIScrollView就OK了。

原理:
scrollView的pan手勢會(huì)讓系統(tǒng)的pan手勢失效,所以我們只需要在系統(tǒng)手勢失效且scrollView的位置在初始位置的時(shí)候讓兩個(gè)手勢同時(shí)啟用就可以了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容