UICollectionView與UITableView混用手勢沖突

來自: http://www.henishuo.com/collectionview-tableview-confliction/

前言

最近在重構某個模塊,以后別人封裝的所謂的基類就像一坨死一樣,看見就惡心,相信同行的你們能夠明白那種心情。為什么要重構?并不是真的因為它像一坨死,而是因為這個模塊是用戶使用最頻繁的,而且出現了不少bug,最重要的是這bug還是p1級別的致命bug。

曾經經過了幾天的壓力測試都沒有復現出來,但是用戶卻頻繁反饋,這就是決定重構的原因了。重構的界面是這樣的:

當UICollectionView中的每個cell放的是一個controller.view而這個controller.view又放一個UITableVIew時,這時候將collectionView的滾動方向設置為橫向就可以了。

但是,如果我們設置了bounces為YES,那么右滑返回手勢就沒有了,怎么辦?

實現思路

共使用了四個控制器類:

  • ContentController:手勢沖突當前所在的控制器,使用UICollectionView,每個cell對應于一個控制器的view
  • SiteController1:標簽一對應的控制器
  • SiteController2:標簽二對應的控制器
  • SiteController3:標簽三對應的控制器

配置UICollectioView

 
// config collection view
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init];
layout.itemSize = CGSizeMake(kScreenWidth, kScreenHeight - 64 - tabViewHeight);
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.minimumLineSpacing = 0;
layout.minimumInteritemSpacing = 0;
self.collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 64 + tabViewHeight, kScreenWidth, kScreenHeight - 64 - tabViewHeight)
                                       collectionViewLayout:layout];
[self.viewaddSubview:self.collectionView];
self.collectionView.backgroundColor = kWColor;
self.collectionView.pagingEnabled = YES;
self.collectionView.showsHorizontalScrollIndicator = NO;
  
[self.collectionViewregisterClass:[UICollectionViewCell class]
      forCellWithReuseIdentifier:kPatientCellIdentifier];
[self.collectionViewregisterClass:[UICollectionViewCell class]
      forCellWithReuseIdentifier:kUnreadCellIdentifier];
[self.collectionViewregisterClass:[UICollectionViewCell class]
      forCellWithReuseIdentifier:kAllCellIdentifier];
      
// 不能將bounces設置為NO,否則右滑返回手勢就沒有了
// self.collectionView.bounces = NO;
 

當我們滾動到標簽三時,再滑動就會超出范圍,此時會顯示部分空白,這體驗不太好,不希望可以再滑動了。同樣,當滑動到標簽一時,再右滑時,不希望顯示空白部分,而是觸發右滑返回手勢。

解決方案

解決方案就是實現UIScrollView的代理方法,當超出屏寬*2時,限制在屏寬*2的位置處。同樣,當小于0時,就限制在0處,這樣就解決了出現空白的問題。同時,這樣就不會關閉用戶響應,因此系統的右滑返回手勢仍然可以觸發。

經過這么一折騰,大家明白如何解決的了嗎?

 
#pragma mark -- UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
  // 限制不能超出屏寬*2
  if (scrollView.contentOffset.x > 2 * kScreenWidth) {
    [scrollViewsetContentOffset:CGPointMake(2 * kScreenWidth, 0)];
    return;
  }
  
  // 限制不能超過0
  if (scrollView.contentOffset.x < 0) {
    [scrollViewsetContentOffset:CGPointMake(0, 0)];
    return;
  }
  
  int itemIndex = (scrollView.contentOffset.x +
                  self.collectionView.hdf_width* 0.5) / self.collectionView.hdf_width;
  itemIndex = itemIndex % [selfcollectionView:self.collectionViewnumberOfItemsInSection:0];
  
  CGFloat x = scrollView.contentOffset.x - self.collectionView.hdf_width;
  NSUInteger index = fabs(x) / self.collectionView.hdf_width;
  CGFloat fIndex = fabs(x) / self.collectionView.hdf_width;
  
  if (fabs(fIndex - (CGFloat)index) <= 0.00001) {
    // ....切換按鈕
  }
}
 

最后

本篇文章沒有demo,因為這是在公司項目中所寫的,這里只是將簡單的部分總結寫出來,希望后來人可以快速填埋這個坑。

本篇文章所涉及的問題,也許與您所遇到的問題有些區別,但是希望本篇文章可以給您聯想!!!

關注我

關注 賬號 備注
Swift/ObjC技術群一 324400294 群一若已滿,請申請群二
Swift/ObjC技術群二 494669518 群二若已滿,請申請群三
Swift/ObjC技術群三 461252383 群三若已滿,會有提示信息
關注微信公眾號 iOSDevShares 關注微信公眾號,會定期地推送好文章
關注新浪微博賬號 標哥Jacky 關注微博,每次發布文章都會分享到新浪微博
關注標哥的GitHub CoderJackyHuang 這里有很多的Demo和開源組件
關于我 進一步了解標哥 如果覺得文章對您很有幫助,可捐助我!

版權聲明:本文為【標哥的技術博客】原創出品,歡迎轉載,轉載時請注明出處!

 本文由用戶 喜新厭舊 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!