如果你重写了tableView: commitEditingStyle: forRowAtIndexPath:函数,那么UITableViewCell在非编辑状态从右向左侧滑,右边会出现红色的“删除”按钮。但如何像微信一样定制button呢?
iOS8以前
在iOS8以前(应该猜到了在iOS8开始后会有更直接的办法,之后会说到),Apple没有提供直接修改button的API,我们必须用很纠结的方法来进行设置。
1.cell的subviews结构
先看看iOS7时cell的subviews结构:
- UITableViewCell
- UITableViewCellScrollView
- UITableViewCellDeleteConfirmationView
- UITableViewCellDeleteConfirmationButton
- UITableViewCellContentView
- UITableViewCellSeparatorView
找到了这个DeleteConfirmationButton,我们只需要把它替换成我们自己的buttonMenu就行了。
2.实现方法
在iOS7.1之前,DeleteConfirmationButton一直存在,可以重写layoutSubviews,在这个函数内获取DeleteConfirmationButton。
但是从iOS7.1开始,cell为editing状态时DeleteConfirmationButton才存在。为了找到最合适的替换原来DeleteConfirmationButton的timing,进行了诸多尝试:
scrollViewWillBeginDragging_
scrollViewDidScroll_
updateConstraints
updateNavBarButtons
tableView_didEndEditingRowAtIndexPath_
tableView_willBeginEditingRowAtIndexPath_
tableView_commitEditingStyle_forRowAtIndexPath_
UITableViewCellScrollView_addSubview_
UITableViewCellScrollView_scrollViewDidScroll_
UITableViewCellScrollView_setContentOffset_
还有一个名字长得特别像能work的函数scrollViewWillEndDragging_withVelocity_targetContentOffset_,但当在它里面替换button时,我们会看到cell左移时原来的系统deletebutton,在释放cell的瞬间变成我们设置的buttonMenu。
最后能够实现预期效果的是UITableViewCellScrollView_setContentOffset_,当然我们不能在这个函数里面直接替换DeleteConfirmationButton而不做任何判断,因为它会在cell scroll时调用N次,而我们只需要做一次替换DeleteConfirmationButton的操作。
大致的实现逻辑如下:
(其中DView代表UITableViewCellDeleteConfirmationView,DButton代表UITableViewCellDeleteConfirmationButton)
(1) 在UITableViewCellScrollView_setContentOffset_中
- 若整个table为编辑状态,则不做处理
- 否则:从Cell的subviews中按照层次关系提取出DView和DButton。若DView不存在,则返回;
- 否则:获取DView的subviews中是否有buttonMenu,若有则表示已经替换过button,并返回;
- 否则:初始化buttonMenu,把它加到DView中,并修改DView和DButton的width;
- 否则:获取DView的subviews中是否有buttonMenu,若有则表示已经替换过button,并返回;
- 否则:从Cell的subviews中按照层次关系提取出DView和DButton。若DView不存在,则返回;
(2) 在PHRecentsCell_scrollViewWillEndDragging_withVelocity_targetContentOffset_函数中中根据buttonMenu中所有Button的宽度之和,设置cell scroll停留的位置(如果不设置,cell完成左滑动作后会停留在系统本身的DButton的左边缘位置)。
iOS8开始
刚提到了iOS7和7.1cell中DeleteConfirmationButton的出现时机是不一样的,而到了iOS8,cell连层级结构都变了╮(╯_╰)╭。
- UITableViewCell
- UITableViewCellDeleteConfirmationView
- _UITableViewCellActionButton
- UITableViewCellContentView
- UITableViewLabel
- _UITableViewCellSeparatorView
- UITableViewCellDeleteConfirmationView
但幸运的是我们不需要像iOS7那样自己写一个buttonMenu替换系统button,因为Apple在iOS8开放了一个API,用于定制cell左滑时的buttons:
- (nullable NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath;
函数返回的类型是NSArray,其中包含的是UITableViewRowAction类型的对象,我们可以设置这个对象的title、backgroundColor、handler等:
UITableViewRowAction *action = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"删除" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
//button按下的处理
}];
action.backgroundColor = [UIColor orangeColor];
虽然button的数量没有限制,但由于button的宽度是系统根据button 的 title进行自动的适应,所以如果buttons的累计宽度太大,在cell里会显示不下。建议在编写代码的具体过程中,考虑不同尺寸屏幕上的显示效果。
本文介绍了在iOS8以前和以后如何定制UITableViewCell左滑时的删除按钮,包括修改cell的subviews结构,以及利用iOS8提供的API实现自定义操作。

4899

被折叠的 条评论
为什么被折叠?



