原文 : 與佳期的個(gè)人博客(gonghonglou.com)
前段時(shí)間公司項(xiàng)目中遇到的問題吵聪,解決之后想著寫篇博客總結(jié)一下但苦于一直沒有時(shí)間劲装,以致拖到了現(xiàn)在胧沫,馬上過年了現(xiàn)在來還賬昌简。。绒怨。
項(xiàng)目中需要實(shí)現(xiàn)以下這種頁面纯赎,需求:
1、在 UIScrollView
上嵌套左右兩個(gè) UITableView
南蹂,以實(shí)現(xiàn)左右滑動(dòng)展示頁面的效果
2犬金、UITableView
可執(zhí)行左滑刪除 cell
功能
然而在實(shí)現(xiàn)過程中發(fā)現(xiàn) UIScrollView
的滾動(dòng)和 UITableView
的左滑刪除存在手勢(shì)沖突,幸好解決方法并不復(fù)雜六剥,不過在實(shí)現(xiàn)過程中還是很捉急的晚顷。
階段一:實(shí)現(xiàn) UITableView 左右滑動(dòng)的效果
這個(gè)效果的實(shí)現(xiàn)還是很簡單的,代碼如下:
CGFloat viewWidth = self.view.frame.size.width;
CGFloat viewHeight = self.view.frame.size.height;
// scroll view
self.scrollView = [[MyScrollView alloc] initWithFrame:self.view.frame];
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.bounces = NO;
self.scrollView.pagingEnabled = YES;
self.scrollView.contentSize = CGSizeMake(viewWidth * 2, 0);
[self.view addSubview:self.scrollView];
// left table view
self.leftTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, viewWidth, viewHeight-160) style:UITableViewStylePlain];
self.leftTableView.backgroundColor = [UIColor whiteColor];
[self.scrollView addSubview:self.leftTableView];
// right table view
self.rightTableView = [[UITableView alloc] initWithFrame:CGRectMake(viewWidth, 0, viewWidth, viewHeight-160) style:UITableViewStylePlain];
[self.scrollView addSubview:self.rightTableView];
這個(gè)階段可能遇到的情況也許是疗疟,如果當(dāng)前頁面是被前一個(gè)頁面通過 navigationController push 出來的話该默,實(shí)現(xiàn)這種效果后可能會(huì)導(dǎo)致邊緣觸發(fā)返回手勢(shì)實(shí)效,如果該手勢(shì)失效應(yīng)該檢查:
1策彤、系統(tǒng)邊緣觸發(fā)返回手勢(shì)是否開啟
self.navigationController.interactivePopGestureRecognizer.enabled = YES;
2栓袖、在該頁面是否自定義了導(dǎo)航條的返回按鈕
如果自定義了導(dǎo)航條的返回按鈕,系統(tǒng)自帶的邊緣觸發(fā)返回手勢(shì)將會(huì)實(shí)效店诗,解決方法是設(shè)置代理 UIGestureRecognizerDelegate
裹刮,并設(shè)置:
self.navigationController.interactivePopGestureRecognizer.delegate = self;
然后重載其代理方法:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
// 導(dǎo)航的 rootViewController 關(guān)閉右滑返回功能
if (self.navigationController.viewControllers.count <= 1) {
return NO;
}
return YES;
}
階段二:實(shí)現(xiàn) UITableView 左滑刪除功能
這一階段還是比較坑的
在實(shí)現(xiàn)了 editActionsForRowAtIndexPath:
代理方法之后發(fā)現(xiàn)并沒有出現(xiàn)左滑刪除功能,因?yàn)樵撌謩?shì)被 UIScrollView
攔截了庞瘸,只有快速左滑時(shí)才有可能出現(xiàn)左滑刪除按鈕必指,但這明顯不符合操作習(xí)慣
然后發(fā)現(xiàn)將 scrollView
的 scrollEnabled
屬性設(shè)置為 NO
時(shí),便出現(xiàn)了左滑刪除按鈕恕洲,即:
self.scrollView.scrollEnabled = NO;
最初想到的解決方案是:
1、通過 touchesBegan:
梅割、touchesMoved:
等方法判斷觸摸點(diǎn)出現(xiàn)的位置
2霜第、如果斷觸摸點(diǎn)出現(xiàn)在 UITableView
區(qū)域,則設(shè)置 scrollView.scrollEnabled = NO;
户辞,否則設(shè)置 scrollView.scrollEnabled = YES;
然而實(shí)際操作之后發(fā)現(xiàn)泌类,根本不會(huì)調(diào)用 touchesBegan:
、touchesMoved:
等方法底燎,看來 UIScrollView
將這些方法也攔截了刃榨。
卒!
而且后來也發(fā)現(xiàn)即使這個(gè)方法生效也并不合理双仍,因?yàn)閷?duì)于左邊的 UITableView
來說枢希,當(dāng)數(shù)據(jù)源過少,cell
并不能填滿 UITableView
區(qū)域時(shí)朱沃,下半部份空白的 UITableView
區(qū)域并不能觸發(fā) UIScrollView
的滾動(dòng)苞轿,因?yàn)槲覀儾⒉恢?UITableView
區(qū)域是否被填滿茅诱。
而我們期望的最優(yōu)秀的表現(xiàn)應(yīng)該是當(dāng)對(duì)左邊的 UITableView
執(zhí)行左滑手勢(shì)時(shí):
1、如果 觸摸點(diǎn)所在區(qū)域存在 cell 時(shí)搬卒,觸發(fā)左滑刪除功能
2瑟俭、否則 觸發(fā) UIScrollView
的滾動(dòng)
(當(dāng)然可以根據(jù)數(shù)據(jù)源計(jì)算 cell
高度來判斷,但這樣就依賴了數(shù)據(jù)源并且這種根據(jù)數(shù)據(jù)計(jì)算控件高度來做判斷的方法也太蠢了契邀。摆寄。。)
所以最終的解決方案是自己實(shí)現(xiàn)一個(gè) MyScrollView
繼承自 UIScrollView
坯门,并重載 - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
代理方法:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if (gestureRecognizer.state != 0) {
return YES;
} else {
return NO;
}
}
這樣微饥,當(dāng) ScrollView
識(shí)別到左滑手勢(shì)時(shí)仍然能向下傳遞該手勢(shì)給它的子視圖,手勢(shì)識(shí)別的流程應(yīng)當(dāng)是:
1田盈、ScrollView
識(shí)別到左滑手勢(shì)畜号,觸發(fā)滾動(dòng)功能的同時(shí)將該手勢(shì)傳遞給它的子視圖 UITableView
2、UITableView
傳遞該手勢(shì)給它的子視圖 UITableViewCell
3允瞧、如果存在子視圖 UITableViewCell
則觸發(fā)左滑刪除功能
目前為止简软,已經(jīng)可以實(shí)現(xiàn)在 UIScrollView
上嵌套左右兩個(gè) UITableView
左右滑動(dòng)的功能,并且 UITableView
存在左滑刪除功能述暂,但執(zhí)行左滑刪除時(shí) UIScrollView
仍在滾動(dòng)痹升,顯然不合理,幸好畦韭,UIScrollView
給我們提供了如下兩個(gè)方法疼蛾,我們可以在左滑刪除手勢(shì)的開始和完成的時(shí)機(jī)設(shè)置 scrollView.scrollEnabled
:
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath {
self.scrollView.scrollEnabled = NO;
}
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(nullable NSIndexPath *)indexPath {
self.scrollView.scrollEnabled = YES;
}
即 當(dāng)左滑刪除開始時(shí)禁止 UIScrollView
滾動(dòng),當(dāng)左滑刪除完成時(shí)開啟 UIScrollView
的滾動(dòng)艺配。
至此便解決了 UIScrollView
左右滾動(dòng)和 UITableView
左滑刪除手勢(shì)沖突的問題察郁。
后記
小白出手,請(qǐng)多指教转唉。如言有誤皮钠,還望斧正!
轉(zhuǎn)載請(qǐng)保留原文地址:http://gonghonglou.com/2018/02/11/scrollview-tableview/