简体   繁体   English

完全滑动UITableViewCell以删除UITableView iOS 8

[英]Full swipe UITableViewCell to delete UITableView iOS 8

I'd like to mimic the swipe to delete function of a UITableViewCell just like the mail app in iOS 8. I'm not referring to swipe to reveal a delete button. 我想模仿滑动删除UITableViewCell的功能,就像iOS 8中的邮件应用程序一样。我不是指滑动以显示删除按钮。 I'm referring to when you swipe, it discoloses 3 actions, but if you keep swiping to the left, the email is deleted. 我指的是当你刷卡时,它会破坏3个动作,但是如果你继续向左滑动,那么电子邮件就会被删除。

In iOS 8, UITableView has a new method where you can provide the data to display any number of buttons: 在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

I don't see any API to detect if you keep swiping though. 我没有看到任何API来检测你是否继续刷卡。 I've grepped for 8_0 in UITableView.h and the above method seems to be the only new one. 我在UITableView.h中使用了8_0,上面的方法似乎是唯一的新方法。

I suppose one could monitor the scroll view offset, or add/hijack a UIPanGestureRecognizer. 我想可以监视滚动视图偏移,或添加/劫持UIPanGestureRecognizer。 I just wanted to make sure to use the default way, if there is one (and get the animation for "free") 我只是想确保使用默认方式,如果有的话(并获得“免费”动画)

With Swift 4.2 and iOS 12, according to your needs, you can choose one of the 3 following ways in order to create a trailing swipe action that will delete the selected UITableViewCell . 使用Swift 4.2和iOS 12,您可以根据需要选择以下3种方法之一,以创建将删除所选UITableViewCell的拖尾滑动操作。


#1. #1。 Using UITableViewDataSource 's tableView(_:commit:forRowAt:) 使用UITableViewDataSourcetableView(_:commit:forRowAt:)

When you use tableView(_:commit:forRowAt:) with an editingStyle of value UITableViewCell.EditingStyle.delete , full swipe to delete is automatically supported by the system. 当您使用tableView(_:commit:forRowAt:)和值为UITableViewCell.EditingStyle.deleteeditingStyle ,系统会自动支持完全滑动删除。

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. #2。 Using UITableViewDelegate 's tableView(_:editActionsForRowAt:) and UITableViewRowAction 使用UITableViewDelegatetableView(_:editActionsForRowAt:)UITableViewRowAction

In order to support full swipe to delete with UITableViewRowAction , you have to initialize it with a style that has a value of UITableViewRowAction.Style.destructive . 为了支持使用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. #3。 Using UITableViewDelegate 's tableView(_:trailingSwipeActionsConfigurationForRowAt:) and UISwipeActionsConfiguration (requires iOS 11) 使用UITableViewDelegatetableView(_:trailingSwipeActionsConfigurationForRowAt:)UISwipeActionsConfiguration (需要iOS 11)

UISwipeActionsConfiguration has a property called performsFirstActionWithFullSwipe . UISwipeActionsConfiguration有一个叫做财产performsFirstActionWithFullSwipe performsFirstActionWithFullSwipe has the following declaration: performsFirstActionWithFullSwipe具有以下声明:

var performsFirstActionWithFullSwipe: Bool { get set }

A Boolean value indicating whether a full swipe automatically performs the first action. 一个布尔值,指示完全滑动是否自动执行第一个操作。 [...] When this property is set to true , a full swipe in the row performs the first action listed in the actions property. [...]当此属性设置为true ,行中的完全滑动将执行actions属性中列出的第一个操作。 The default value of this property is true . 此属性的默认值为true

The following UITableViewController implementation show how to use UISwipeActionsConfiguration in order to manage full swipe to delete actions. 以下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
    }

}

add ui gustere recognizer to each cell, check the amount of "swipness", if its above specific threshold, do the deletion. 将ui gustere识别器添加到每个单元格中,检查“swipness”的数量,如果超过特定阈值,则执行删除操作。

somthing like: 像这样的东西:

    - (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");
        }

    }
}

Your table view's data source has to implement 您的表视图的数据源必须实现

-tableView:commitEditingStyle:forRowAtIndexPath:

otherwise the built-in iOS 8 swiping functionality will not work. 否则内置的iOS 8滑动功能将无法正常工作。

This seems counterintuitive since a UITableViewRowAction accepts a block. 这似乎违反直觉,因为UITableViewRowAction接受一个块。 But it's the only way I've been able to get it to work. 但这是我能够让它发挥作用的唯一方法。

You can use MGSwipeTableCell . 您可以使用MGSwipeTableCell They have implement this feature to fire callback swipeTableCell:tappedButtonAtIndex:direction:fromExpansion: with tappedButtonAtIndex equal to 0 (so it gets executed what you implemented on first added button). 他们已经实现了这个功能来触发回调swipeTableCell:tappedButtonAtIndex:direction:fromExpansion:tappedButtonAtIndex等于0(因此它会执行你在第一次添加的按钮上实现的内容)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM