iOS自定义UITableViewRowAction

先看效果 :

iOS自定义UITableViewRowAction_第1张图片

iOS自定义UITableViewRowAction_第2张图片

 

说下思路:首先要实现tableview的代理。共有几个方法:

1:

-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
    return YES;
}

-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
    return UITableViewCellEditingStyleDelete ;
}

- (NSArray *)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);
    }];
}

到此为止,大功告成

 

其他文章请查看个人博客:http://zhangqq166.cn/

本人创建了一个公众号,里面每天发一些教程进阶知识,有的是本人总结所得,有的是转载大神的文章,大家一起分享看。

你可能感兴趣的:(iOS技术文档,控件)