iOS自定义UITableViewRowAction
先看效果 :
说下思路:首先要实现tableview的代理。共有几个方法:
1:
-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewCellEditingStyleDelete ;
}
- (NSArray<UITableViewRowAction *> *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{
WEAK_SELF;
UITableViewRowAction *deleteRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"删除"handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
NSLog(@"点击了删除");
[tableView setEditing:NO animated:YES];
AddressRecord *record = weakSelf.addressArray[indexPath.row];
[weakSelf deleteAddress:record.id];
}];
deleteRowAction.backgroundColor = ColorRGB(83, 80, 84);
UITableViewRowAction *setDefaultAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"设置默认"handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
AddressRecord *record = weakSelf.addressArray[indexPath.row];
[tableView setEditing:NO animated:YES];
[weakSelf setDefaultAddress:record.id];
}];
setDefaultAction.backgroundColor = ColorRGB(169, 166, 170);
AddressRecord *record = self.addressArray[indexPath.row];
if (record.is_default) {
return @[deleteRowAction];
}else{
return @[deleteRowAction,setDefaultAction];
}
}
以上几个方法能看懂什么意思就不说了 调用这几个方法就能实现侧滑出现自定义button
在iOS11以上。新增了一个方法:
- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath API_AVAILABLE(ios(11.0)){
WEAK_SELF;
if (@available(iOS 11.0, *)) {
UIContextualAction *deleteRowAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal title:@"删除" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
AddressRecord *record = weakSelf.addressArray[indexPath.row];
[weakSelf deleteAddress:record.id];
}];
UIContextualAction *editRowAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal title:@"设置默认" handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
AddressRecord *record = weakSelf.addressArray[indexPath.row];
[tableView setEditing:NO animated:YES];
[weakSelf setDefaultAddress:record.id];
}];
AddressRecord *record = self.addressArray[indexPath.row];
if (record.is_default) {
UISwipeActionsConfiguration *config = [UISwipeActionsConfiguration configurationWithActions:@[deleteRowAction]];
//设置全屏滑动时不自定响应事件
config.performsFirstActionWithFullSwipe = false;
return config;
}else{
UISwipeActionsConfiguration *config = [UISwipeActionsConfiguration configurationWithActions:@[deleteRowAction,editRowAction]];
//设置全屏滑动时不自定响应事件
config.performsFirstActionWithFullSwipe = false;
return config;
}
}else{
return nil;
}
}
这个方法的实现看起来有点熟悉,在iOS11以上的系统中测试的时候用力向左侧滑会发现一个问题,侧滑之后会自动执行第一个action的事件,你没有点击那个action却执行了方法,比如我的demo中最右的action是删除 那么我测试的时候用力左滑之后会自动删除掉当前cell 我以为出bug了。后来查资料看到了这个方法,在iOS11以上的系统实现这个方法可以禁用掉左滑事件。同时自定义action的事件。由于里面的代码跟上面第一步的代理的action的代码一样,所以有些重复,不过能很好的解决这个bug。
3:剩下的就很简单了,在controller中侧滑事件发生后会触发代理:
- (void)tableView:(UITableView *)tableView willBeginEditingRowAtIndexPath:(NSIndexPath *)indexPath {
[self.view setNeedsLayout];
}
在这个代理中让self。view刷新UI,重绘,然后就会调用系统方法:
- (void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
[self configSwipeButtons];
}
configSwipeButtons方法中就是对tableview进行遍历,找到action上面的各个button,对其进行自定义操作就可以。
4:说明:在iOS13和iOS11和iOS10以下这三部分系统,action所在的table的层级和名称是不一样的,所以要加以区分:
- (void)configSwipeButtons{
if (@available(iOS 13.0, *)) {
for (UIView *subview in self.tableView.subviews){
if ([subview isKindOfClass:NSClassFromString(@"_UITableViewCellSwipeContainerView")] ){
for (UIView *actionView in subview.subviews) {
if ([actionView isKindOfClass:NSClassFromString(@"UISwipeActionPullView")]) {
actionView.backgroundColor = COLOR(clearColor);
if (actionView.subviews.count >= 2) {
UIButton *deleteButton = actionView.subviews[1];
UIButton *readButton = actionView.subviews[0];
[self configDeleteButton:deleteButton];
[self configReadButton:readButton];
}else if (actionView.subviews.count <2){
UIButton *deleteButton = actionView.subviews[0];
[self configDeleteButton:deleteButton];
}
}
}
}
}
}else if (@available(iOS 11.0, *)){
// iOS 11层级 (Xcode 8编译): UITableView -> UITableViewWrapperView -> UISwipeActionPullView
for (UIView *subview in self.tableView.subviews){
if ([subview isKindOfClass:NSClassFromString(@"UITableViewWrapperView")]){
for (UIView *actionView in subview.subviews){
if ([actionView isKindOfClass:NSClassFromString(@"UISwipeActionPullView")]){
actionView.backgroundColor = COLOR(clearColor);
if (actionView.subviews.count >= 2) {
UIButton *deleteButton = actionView.subviews[1];
UIButton *readButton = actionView.subviews[0];
[self configDeleteButton:deleteButton];
[self configReadButton:readButton];
}else if (actionView.subviews.count <2){
UIButton *deleteButton = actionView.subviews[0];
[self configDeleteButton:deleteButton];
}
}
}
}
}
}else{
// iOS 8-10层级: UITableView -> UITableViewCell -> UITableViewCellDeleteConfirmationView
AddressTableViewCell *tableCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
for (UIView *subview in tableCell.subviews){
if ([subview isKindOfClass:NSClassFromString(@"UITableViewCellDeleteConfirmationView")] && [subview.subviews count] >= 2){
UIButton *deleteButton = subview.subviews[0];
UIButton *readButton = subview.subviews[1];
[self configDeleteButton:deleteButton];
[self configReadButton:readButton];
}
}
}
}
- (void)configDeleteButton:(UIButton*)deleteButton{
deleteButton.titleLabel.font = FONT_Regular(13);
[deleteButton setTitleColor:COLOR(whiteColor) forState:0];
[deleteButton setBackgroundImage:[UIImage imageWithColor:ColorRGB(80, 83, 86)] forState:0];
deleteButton.layer.cornerRadius = 10;
deleteButton.layer.masksToBounds = YES;
[deleteButton updateConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(W(65));
make.top.equalTo(H(10));
make.bottom.equalTo(-1);
}];
}
- (void)configReadButton:(UIButton*)readButton{
readButton.titleLabel.font = FONT_Regular(13);
[readButton setTitleColor:COLOR(whiteColor) forState:0];
[readButton setBackgroundImage:[UIImage imageWithColor:ColorRGB(169, 166, 170)] forState:0];
readButton.layer.cornerRadius = 10;
readButton.layer.masksToBounds = YES;
[readButton updateConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(W(65));
make.top.equalTo(H(10));
make.bottom.equalTo(-1);
}];
}
到此为止,大功告成
上一篇: react中useState的使用:实现在当前表格直接更改数据
下一篇: 解决使用IDE Run运行出错package pack/test is not in GOROOT (/usr/local/go/src/pack/test)
推荐阅读
-
详解使用DotNet CLI创建自定义的WPF项目模板
-
implicit关键字做自定义类型隐式转换的方法
-
C#实现Menu和ContextMenu自定义风格及contextMenu自定义
-
C#自定义控件添加右键菜单的方法
-
JavaScript自定义DateDiff函数(兼容所有浏览器)
-
基于Android中Webview使用自定义的javascript进行回调的问题详解
-
IOS程序开发之禁止输入表情符号实例代码
-
iOS App开发中UITextField组件的常用属性小结
-
iOS从App跳转至系统设置菜单各功能项的编写方法讲解
-
iOS程序开发中设置UITableView的全屏分隔线的方法(不画线)