在平時項目中,我們經常會碰到類似UIScrollView
嵌套UITableView
的需求,雖然蘋果并不建議這種做法,但是這樣的需求在平時工作中還是很常見的。比如筆者公司項目之前用到的地方:
可以看到最上面是一塊輪播圖組件,我也已經整理了一份輪播圖組件在github上面,輪播圖下面還有若干條其他的內容,而且這幾塊內容都是后臺動態控制顯示的,所以這里用UIScrollView
設置頂部偏移量實現是很不方便的。最外層我肯定選擇使用tableView
分區管理來實現。而下面的橫向分類頁面肯定需要tableView
去實現
這樣的話問題就來了,先不說下面的橫向分頁如何實現,這個頁面必定需要在一個tableView
中嵌套多個不同的tableView
,但是如果嵌套了其他的scrollView
,就需要我們判斷不同條件下讓哪個scrollView
響應滑動事件,因此這里我們需要解決的就是手勢的沖突問題。
最開始想到的是在滑動tableView
時候根據偏移量設置scrollEnabled
來控制兩個tableView
的響應,但是會有個問題就是當滾動到頂部時用戶必須第二次滑動才可以顯示出外層的tableView
,這樣就會造成一個卡頓的效果,所以這個方法是行不通的。
下面說一下我的解決思路:
這里就直接分為mainTableView
和subTableView
,設置mainTableView
的聯動手勢UIGestureRecognizer
/**
同時識別多個手勢
@param gestureRecognizer gestureRecognizer description
@param otherGestureRecognizer otherGestureRecognizer description
@return return value description
*/
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
下面的分類pageView
是直接使用了封裝的page框架FSScrollContentView,在mainTableView
的UIScrollViewDelegate
方法內判斷mainTableView
的偏移量,當標題欄滾動到頂部的時候固定mainTableView
的偏移量
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat bottomCellOffset = [_tableView rectForSection:1].origin.y - 64;
if (scrollView.contentOffset.y >= bottomCellOffset) {
scrollView.contentOffset = CGPointMake(0, bottomCellOffset);
if (self.canScroll) {
self.canScroll = NO;
self.contentCell.cellCanScroll = YES;
}
}else{
if (!self.canScroll) {//子視圖沒到頂部
scrollView.contentOffset = CGPointMake(0, bottomCellOffset);
}
}
self.tableView.showsVerticalScrollIndicator = _canScroll?YES:NO;
}
上面代碼中的canScroll
是定義的一個BOOL
變量用來控制mainTableView
的偏移量
此時,subTableView
收到可以滾動的信號cellCanScroll
,才開始響應滑動的手勢,在subTableView
的UIScrollViewDelegate
方法內實現:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (!self.vcCanScroll) {
scrollView.contentOffset = CGPointZero;
}
if (scrollView.contentOffset.y <= 0) {
if (!self.fingerIsTouch) {
return;
}
self.vcCanScroll = NO;
scrollView.contentOffset = CGPointZero;
[[NSNotificationCenter defaultCenter] postNotificationName:@"leaveTop" object:nil];//到頂通知父視圖改變狀態
}
self.tableView.showsVerticalScrollIndicator = _vcCanScroll?YES:NO;
}
其實到這里會發現主要是通過設置兩個scrollView
的偏移量來解決這個手勢沖突的問題。因為代碼已經表達的很清楚,不太擅長表達,這里只是大概描述一下使用場景。
具體的實現方式已經寫成了一個demo,里面也有詳細的注釋,可以前去下載:FSScrollViewNestTableView
2017.6.21--應網友要求,demo添加了刷新邏輯
給大家看一下實現后的效果圖: