最近有需求需要用到自定義刪除按鈕樣式的UITableViewCell。剛開始采用了修改系統刪除按鈕樣式的方法,效果還可以。可是在iOS11上,由于UITableViewCell刪除按鈕實現形式的改變,這個方法就失效了,而一些第三方庫實現起來既復雜又有限制,因此就寫了個簡單版的,僅供參考。
方式一
思路
找到UITableViewCell的刪除頁面,重寫頁面上的刪除按鈕樣式
方法
- 重寫UITableViewCell的
- (void)layoutSubviews;
方法,通過遍歷subViews的方式找到刪除按鈕所在的頁面UITableViewCellDeleteConfirmationView - 通過遍歷subViews的方式在UITableViewCellDeleteConfirmationView上找到刪除按鈕并移除
- 在UITableViewCellDeleteConfirmationView上添加自定義樣式的刪除按鈕和點擊事件
- 通過控制代理方法
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath;
中返回空格的個數來決定刪除按鈕的寬度 - 需要實現代理方法
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
,就算沒有具體內容也可以
優點
由于只是修改了樣式,因此相關的交互效果與系統的一致
局限性
刪除按鈕的樣式有一定的局限性,并且在iOS11上,UITableViewCell刪除按鈕的實現形式從根本上有了改變,該方法失效
方式二
思路
自定義UITableViewCell
方法
- 為了盡量與系統的交互效果保持一致(即滑動刪除),自定義UITableViewCell的主體控件是UIScrollView
- 所有其它的控件,包括自定義的刪除按鈕都是添加在這個scrollView上的
- 為了滑動后有足夠的空間顯示刪除按鈕,將scrollView的contentSize設置為
CGSizeMake(ScreenWidth + deleteBtnWidth + margin, CellHeight)
- 刪除按鈕的處理方式有兩種:
- 添加在屏幕之外,固定在scrollView上,會隨著scrollView的滑動而逐漸顯示在屏幕上
- 添加在屏幕之內,被另一個頁面遮蓋住。遮蓋它的頁面固定在scrollView上,會隨著scrollView的滑動逐漸移開;而它在scrollView內的位置會隨著scrollView的滑動而不斷改變,使其在屏幕上的位置保持不變
- 為了與系統效果更相近,選擇了方式二,具體代碼如下:
_deleteBtn = [UIButton buttonWithType:UIButtonTypeCustom] ;
_deleteBtn.frame = CGRectMake(ScreenWidth - deleteBtnWidth - margin, 7.5, deleteBtnWidth, CellHeight - 15) ;
[_deleteBtn addTarget:self action:@selector(deleteCell) forControlEvents:UIControlEventTouchUpInside] ;
[_scrollView addSubview:_deleteBtn] ;
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if(scrollView.contentOffset.x > 0) {
_deleteBtn.frame = CGRectMake(scrollView.contentOffset.x + ScreenWidth - deleteBtnWidth - margin, 7.5, deleteBtnWidth, CellHeight - 15) ;
}
else {
_deleteBtn.frame = CGRectMake(ScreenWidth - deleteBtnWidth - margin, 7.5, deleteBtnWidth, CellHeight - 15) ;
}
}
注意
- 由于scrollView會吸收觸摸事件,為了讓tableViewCell能夠接收到觸摸事件,需要重寫scrollView的相關方法:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[[self nextResponder] touchesBegan:touches withEvent:event];
[super touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[[self nextResponder] touchesMoved:touches withEvent:event];
[super touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[[self nextResponder] touchesEnded:touches withEvent:event];
[super touchesEnded:touches withEvent:event];
}
- 在顯示刪除按鈕的情況下點擊tableViewCell需隱藏刪除按鈕:
- (void)clickWithCompletion:(void(^)(void))completion {
if(_scrollView.contentOffset.x > 0) {
//滑動過程中禁止scrollView的交互,防止重復點擊引起的卡頓效果
_scrollView.userInteractionEnabled = NO ;
[UIView animateWithDuration:0.3 animations:^{
[_scrollView setContentOffset:CGPointZero] ;
} completion:^(BOOL finished) {
_scrollView.userInteractionEnabled = YES ;
}] ;
}
else {
completion () ;
}
}
- 由于UITableViewCell的重用機制,如果某一行cell左滑顯示了刪除按鈕,在此情況下滑動tableView,那么將會在其它行出現顯示刪除按鈕的cell。為了解決該問題,需要創建一個對象來記錄每個cell刪除按鈕的顯示情況
優點
刪除按鈕的樣式能夠完全自定義,不受系統的限制
局限性
交互效果與系統的相比有所差異
demo
具體的實現代碼見:https://github.com/bbbxxxbx/-