首页 文章

完全滑动UITableViewCell以删除UITableView iOS 8

提问于
浏览
18

我想模仿滑动删除UITableViewCell的功能,就像iOS 8中的邮件应用程序一样 . 我不是指滑动以显示删除按钮 . 我指的是当你刷卡时,它会破坏3个动作,但是如果你继续向左滑动,那么电子邮件就会被删除 .

在iOS 8中,UITableView有一个新方法,您可以在其中提供数据以显示任意数量的按钮:

#ifdef __IPHONE_8_0
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewRowAction *viewStackRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Stack" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
        SM_LOG_DEBUG(@"View Stack Action");
    }];
    viewStackRowAction.backgroundColor = [UIColor radiusBlueColor];

    UITableViewRowAction *viewUserRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"User" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
        SM_LOG_DEBUG(@"View User Action");
    }];
    viewUserRowAction.backgroundColor = [UIColor radiusLightBlueColor];

    UITableViewRowAction *deleteRowAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Delete" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
        SM_LOG_DEBUG(@"Delete");
    }];
    deleteRowAction.backgroundColor = [UIColor redColor];


    return @[deleteRowAction, viewUserRowAction, viewStackRowAction];
}
#endif

我没有看到任何API来检测你是否继续刷卡 . 我在UITableView.h中使用了8_0,上面的方法似乎是唯一的新方法 .

我想可以监视滚动视图偏移,或添加/劫持UIPanGestureRecognizer . 我只是想确保使用默认方式,如果有的话(并获得“免费”动画)

4 回答

  • 3

    使用Swift 4.2和iOS 12,您可以根据需要选择 3 following ways 中的一个,以创建将删除所选 UITableViewCell 的拖尾滑动操作 .


    #1 . 使用UITableViewDataSource的tableView(_:commit:forRowAt :)

    tableView(_:commit:forRowAt:)editingStyle 的值 UITableViewCell.EditingStyle.delete 一起使用时,系统会自动支持完全滑动以删除 .

    import UIKit
    
    class TableViewController: UITableViewController {
    
        var numbers = [Int](0..<10)
    
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return numbers.count
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            cell.textLabel?.text = "\(numbers[indexPath.row])"
            return cell
        }
    
        override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
            if (editingStyle == UITableViewCell.EditingStyle.delete) {
                self.numbers.remove(at: indexPath.row)
                tableView.deleteRows(at: [indexPath], with: .fade)
            }
        }
    
    }
    

    #2 . 使用UITableViewDelegate的tableView(_:editActionsForRowAt :)和UITableViewRowAction

    为了支持使用 UITableViewRowAction 完全滑动删除,您必须使用值为 UITableViewRowAction.Style.destructivestyle 对其进行初始化 .

    import UIKit
    
    class TableViewController: UITableViewController {
    
        var numbers = [Int](0..<10)
    
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return numbers.count
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            cell.textLabel?.text = "\(numbers[indexPath.row])"
            return cell
        }
    
        override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
            // Intentionally blank in order to be able to use UITableViewRowActions
        }
    
        override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
            let deleteHandler: (UITableViewRowAction, IndexPath) -> Void = { _, indexPath in
                self.numbers.remove(at: indexPath.row)
                tableView.deleteRows(at: [indexPath], with: .fade)
            }
            let deleteAction = UITableViewRowAction(style: UITableViewRowAction.Style.destructive, title: "Delete", handler: deleteHandler)
            // Add more actions here if required
            return [deleteAction]
        }
    
    }
    

    #3 . 使用UITableViewDelegate的tableView(_:trailingSwipeActionsConfigurationForRowAt :)和UISwipeActionsConfiguration(需要iOS 11)

    UISwipeActionsConfiguration 有一个名为performsFirstActionWithFullSwipe的属性 . performsFirstActionWithFullSwipe 有以下声明:

    var performsFirstActionWithFullSwipe: Bool { get set }
    

    一个布尔值,指示完全滑动是否自动执行第一个操作 . [...]当此属性设置为true时,行中的完全滑动将执行actions属性中列出的第一个操作 . 此属性的默认值为true .

    以下 UITableViewController 实现显示如何使用 UISwipeActionsConfiguration 来管理完全滑动以删除操作 .

    import UIKit
    
    class TableViewController: UITableViewController {
    
        var numbers = [Int](0..<10)
    
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return numbers.count
        }
    
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            cell.textLabel?.text = "\(numbers[indexPath.row])"
            return cell
        }
    
        override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
            let handler: UIContextualAction.Handler = { (action: UIContextualAction, view: UIView, completionHandler: ((Bool) -> Void)) in
                self.numbers.remove(at: indexPath.row)
                tableView.deleteRows(at: [indexPath], with: .fade)
                completionHandler(true)
            }
            let deleteAction = UIContextualAction(style: UIContextualAction.Style.destructive, title: "Delete", handler: handler)
            // Add more actions here if required
            let configuration = UISwipeActionsConfiguration(actions: [deleteAction])
            configuration.performsFirstActionWithFullSwipe = true
            return configuration
        }
    
    }
    
  • 0

    将ui gustere识别器添加到每个单元格中,检查“swipness”的数量,如果超过特定阈值,则执行删除操作 .

    像这样的东西:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
        {
            static NSString *CellIdentifier = @"identifier";
    
            UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
            if (cell == nil) {
                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]];
            }
    
            UISwipeGestureRecognizer* swipe_gesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeLeft:)];
            [swipe_gesture setDirection:UISwipeGestureRecognizerDirectionLeft];
            [cell addGestureRecognizer:swipe_gesture];
    
    
            return cell;
        }
    
    - (void)swipeLeft:(UIGestureRecognizer *)gestureRecognizer {
        int threshold = 100;
        if (sender.state == UIGestureRecognizerStateBegan) 
        {
            startLocation = [sender locationInView:self.view];
        }
        else if (sender.state == UIGestureRecognizerStateEnded) 
        {
            CGPoint stopLocation = [sender locationInView:self.view];
            CGFloat dx = stopLocation.x - startLocation.x;
            CGFloat dy = stopLocation.y - startLocation.y;
            CGFloat distance = sqrt(dx*dx + dy*dy );
            if (distance > threshold )
            {
                NSLog(@"DELETE_ROW");
            }
    
        }
    }
    
  • 2

    您的表视图的数据源必须实现

    -tableView:commitEditingStyle:forRowAtIndexPath:
    

    否则内置的iOS 8滑动功能将无法正常工作 .

    这似乎违反直觉,因为 UITableViewRowAction 接受了一个块 . 但是_2468503已经能够让它发挥作用 .

  • 0

    你可以使用MGSwipeTableCell . 他们已经实现了这个功能来触发回调swipeTableCell:tappedButtonAtIndex:direction:fromExpansion:tappedButtonAtIndex等于0(因此它会执行你在第一次添加的按钮上实现的内容) .

相关问题