一、需求
1慰安、UIScrollView上有兩個子控件UITableView(分別稱作table1,table2)水平布局狸臣,作為左右滑動的分頁
2、第一個UITableView的cell元素支持左滑彈出刪除按鈕刪除和可選擇刪除功能
二粉寞、遇到的問題
1尼荆、table1元素左滑時UIScrollview會將該手勢捕獲導(dǎo)致左滑刪除按鈕不顯示
2、進入編輯模式table1需要有可以選擇的功能唧垦,table1編輯模式下的cell選中和不選中的圖片需要替換
3捅儒、左滑刪除的圖片需要替換
4、ios11之前和ios11之后cell的刪除左滑刪除按鈕彈出后層級有變化
三振亮、手勢問題解決
1巧还、創(chuàng)建UIScrollView的拓展類,并重寫shouldRecognizeSimultaneouslyWithGestureRecognizer方法坊秸,該方法返回YES表示手勢向下傳遞
//是否支持多手勢觸發(fā)麸祷,返回YES,則可以多個手勢一起觸發(fā)方法褒搔,返回NO則為互斥
//是否允許多個手勢識別器共同識別阶牍,一個控件的手勢識別后是否阻斷手勢識別繼續(xù)向下傳播,默認(rèn)返回NO星瘾;
//如果為YES走孽,響應(yīng)者鏈上層對象觸發(fā)手勢識別后,如果下層對象也添加了手勢并成功識別也會繼續(xù)執(zhí)行琳状,否則上層對象識別后則不再繼續(xù)傳播
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if (gestureRecognizer.state != 0) {
NSLog(@"gestureRecognizer.state != 0");
return YES;
} else {
NSLog(@"gestureRecognizer.state == 0");
return NO;
}
}
?? 開始左滑時需要讓uiscrollView不能滾動磕瓷,結(jié)束刪除編輯后需要讓uiscrollview能夠滾動。開始左滑和結(jié)束刪除編輯會回調(diào)下面兩個方法,beginEditingBlock和endEditingBlock分別是禁止?jié)L動和允許滾動方法困食。
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath {
self.beginEditingBlock();
}
//結(jié)束左滑
- (void)tableView:(UITableView *)tableView didEndEditingRowAtIndexPath:(nullable NSIndexPath *)indexPath {
self.endEditingBlock();
}
四边翁、刪除狀態(tài)和多選狀態(tài)兼容
?? ? 點擊右上角編輯按鈕tableview進入編輯狀態(tài),此時可以多選cell
//編輯狀態(tài)下 刪除狀態(tài)|多選狀態(tài)
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView.isEditing) {//點擊右上角編輯按鈕tableview進入編輯狀態(tài)陷舅,此時可以多選cell
// 多選
return UITableViewCellEditingStyleDelete | UITableViewCellEditingStyleInsert;
}else{
// 刪除
return UITableViewCellEditingStyleDelete;
}
}
//編輯狀態(tài)下可編輯的indexpath
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
?? ? 此時可以響應(yīng)tableview的didselect和didDeselect方法倒彰,用NSMutableSet數(shù)組保存是否選中的元素index,在顯示的時候根據(jù)是否選中顯示我們自定義的圖片
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
Cell *chatCell = (Cell *)cell;
//是否在編輯狀態(tài)
if(self.mainTableV.isEditing == YES){
//判斷選中的set里面是否有該行
NSInteger index = indexPath.row;
if([self.chooseSet containsObject:[NSNumber numberWithLong:index]]){
UIImageView *imageView = [[[cell.subviews lastObject]subviews]firstObject];
imageView.image = [UIImage imageNamed:@"choose"];
}
else{
UIImageView *imageView = [[[cell.subviews lastObject]subviews]firstObject];
imageView.image = [UIImage imageNamed:@"nochoose"];
}
}
}
}
五莱睁、左滑刪除按鈕的操作
?? ? 實現(xiàn)editActionsForRowAtIndexPath回調(diào)待讳,編輯左滑按鈕數(shù)組,可以實現(xiàn)多個左滑按鈕仰剿,此處只實現(xiàn)刪除按鈕
//實現(xiàn)刪除按鈕
- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
// 這里的標(biāo)題我使用的 4 個空格進行占位
UITableViewRowAction *action = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@" " handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
//點擊按鈕的操作實現(xiàn)
}];
return @[action];
}
六创淡、左滑按鈕的圖片替換(重點)
?? ? ios11之前,可以在自定義的cell里實現(xiàn)layoutsubviews方法南吮,找到刪除按鈕控件并替換圖片琳彩。到了ios11之后左滑cell刪除按鈕的視圖層級已經(jīng)不在cell里面,所以不能用此方法去重新設(shè)置刪除按鈕圖片
我們來看下左滑時cell的層級部凑,以項目中聊天元素McChatCell左滑為例露乏,測試機ios10的左滑cell層級:
UITableViewCellActionButton是左滑出現(xiàn)的按鈕層級,它在MCChatCell的層級下面涂邀,是UITableViewCellActionButton這個視圖瘟仿。
測試機ios13的左滑cell層級:
ios11之后左滑導(dǎo)致整個cell被包裹在UITableViewCellSwipeContainerView這個控件里面,UISwipeActionStandardButton是左滑出現(xiàn)的刪除按鈕視圖比勉。
?? ?明顯可以看到左滑出刪除按鈕時測試機ios10系統(tǒng)刪除按鈕在自定義cell層級內(nèi)劳较,但是測試機ios13的刪除按鈕層級和自定義cell處于同一層層級,所以ios11之后不能使用重寫自定義cell的layoutsubviews方式去修改刪除按鈕的圖片浩聋。
-(void)layoutSubviews{
[super layoutSubviews];
//遍歷子視圖观蜗,找出左滑按鈕UITableViewCellDeleteConfirmationView
//ios11之前
NSString *systemVersion = [[UIDevice currentDevice] systemVersion];
if(systemVersion.floatValue < 11.0){
for (UIView *subView in self.subviews)
{
if([subView isKindOfClass:NSClassFromString(@"UITableViewCellDeleteConfirmationView")])
{
for (UIButton *btn in subView.subviews) {
if ([btn isKindOfClass:[UIButton class]]) {
//更改左滑按鈕樣式自定義
[btn setImage:[UIImage imageNamed:@"mc_message_delete"] forState:UIControlStateNormal];
[btn setBackgroundColor:McHexColor(0xEC6260)];
}
}
}
}
}
}
?? ? ios11之后可以直接實現(xiàn)uitableview的代理trailingSwipeActionsConfigurationForRowAtIndexPath便可以實現(xiàn)刪除圖片的自定義
// ios11之后的tableview提供的修改刪除按鈕樣式的回調(diào)
-(UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath{
//刪除
if (@available(iOS 11.0, *)) {
mcWeakSelf(weakSelf);
UIContextualAction *delete = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:@" " handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
//實現(xiàn)刪除按鈕點擊操作
}];
delete.image = [UIImage imageNamed:@"delete"];//這里還可以設(shè)置圖片
UISwipeActionsConfiguration *config = [UISwipeActionsConfiguration configurationWithActions:@[delete]];
return config;
} else {
return nil;
}
}
總結(jié)
?? ? 做這個模塊功能踩了很多坑,主要是uitableview的代理和一些處理方法在系統(tǒng)升級后有了改動衣洁,cell左滑后層級也有變化墓捻,在修改刪除按鈕和多選按鈕圖片的方式也要做響應(yīng)修改。而且table的一些代理方法達(dá)到的效果有重疊坊夫,比如trailingSwipeActionsConfigurationForRowAtIndexPath和editActionsForRowAtIndexPath實現(xiàn)點擊刪除按鈕方法毙替,但是trailingSwipeActionsConfigurationForRowAtIndexPath只有在ios11之后才有效,而且如果不實現(xiàn)editActionsForRowAtIndexPath這個方法cell左滑也不會出現(xiàn)刪除按鈕效果践樱,所以ios11之后這兩個方法都需要實現(xiàn),這些很容易讓人迷惑