滑动到删除和"更多"按钮(就像在iOS 7上的邮件应用程序中一样)

Guy*_*lon 246 user-interface cocoa-touch uitableview ios swipe-gesture

用户在表格视图中滑动单元格时如何创建"更多"按钮(如ios 7中的邮件应用程序)

我一直在这里和Cocoa Touch论坛上寻找这些信息,但我似乎无法找到答案,我希望比我更聪明的人能给我一个解决方案.

我希望当用户滑动表格视图单元格时,显示多个编辑按钮(默认为删除按钮).在iOS 7的Mail应用程序中,您可以滑动删除,但会显示一个"更多"按钮.

在此输入图像描述

Joh*_*nny 126

如何实施

看起来iOS 8打开了这个API.Beta 2中提供了此类功能的提示.

要使某些工作正常,请在UITableView的委托上实现以下两种方法以获得所需的效果(请参阅gist以获取示例).

- tableView:editActionsForRowAtIndexPath:
- tableView:commitEditingStyle:forRowAtIndexPath:
Run Code Online (Sandbox Code Playgroud)


已知的问题

文档说tableView:commitEditingStyle:forRowAtIndexPath是:

"不使用UITableViewRowAction调用编辑操作 - 将调用操作的处理程序."

但是,如果没有它,滑动就无法工作.即使方法存根是空白的,它现在仍然需要它.这显然是beta 2中的一个错误.


来源

https://twitter.com/marksands/status/481642991745265664 https://gist.github.com/marksands/76558707f583dbb8f870

原答案:https://stackoverflow.com/a/24540538/870028


更新:

这个工作的示例代码(在Swift中):http://dropbox.com/s/0fvxosft2mq2v5m/DeleteRowExampleSwift.zip

示例代码在MasterViewController.swift中包含这个易于理解的方法,只需使用此方法,您就可以获得OP屏幕截图中显示的行为:

override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {

    var moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "More", handler:{action, indexpath in
        println("MORE•ACTION");
    });
    moreRowAction.backgroundColor = UIColor(red: 0.298, green: 0.851, blue: 0.3922, alpha: 1.0);

    var deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Delete", handler:{action, indexpath in
        println("DELETE•ACTION");
    });

    return [deleteRowAction, moreRowAction];
}
Run Code Online (Sandbox Code Playgroud)

  • 回答我自己的评论.你调用`tableView.editing = false`(objc中的`NO`),单元格将"关闭". (3认同)

Mor*_*oro 121

我创建了一个新的库来实现可交换按钮,它支持各种转换和可扩展按钮,如iOS 8邮件应用程序.

https://github.com/MortimerGoro/MGSwipeTableCell

该库兼容所有不同的创建UITableViewCell的方法,并在iOS 5,iOS 6,iOS 7和iOS 8上进行测试.

这里有一些过渡的样本:

边境过渡:

边境过渡

剪辑转换

剪辑转换

3D过渡:

在此输入图像描述


tim*_*ykc 71

约翰尼的回答是正确的回答.我只是在objective-c中添加以下内容,以使初学者(以及那些拒绝学习Swift语法的人)更清楚:)

确保声明uitableviewdelegate并具有以下方法:

 -(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath {
 UITableViewRowAction *button = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 1" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
    {
        NSLog(@"Action to perform with Button 1");
    }];
    button.backgroundColor = [UIColor greenColor]; //arbitrary color
    UITableViewRowAction *button2 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"Button 2" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
                                    {
                                        NSLog(@"Action to perform with Button2!");
                                    }];
    button2.backgroundColor = [UIColor blueColor]; //arbitrary color

    return @[button, button2]; //array with all the buttons you want. 1,2,3, etc...
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
// you need to implement this method too or nothing will work:

}
 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
    {
        return YES; //tableview must be editable or nothing will work...
    }
Run Code Online (Sandbox Code Playgroud)


Jon*_*an. 25

这是(相当荒谬)一个私有API.

以下两个方法是私有的并发送到UITableView的委托:

-(NSString *)tableView:(UITableView *)tableView titleForSwipeAccessoryButtonForRowAtIndexPath:(NSIndexPath *)indexPath;
-(void)tableView:(UITableView *)tableView swipeAccessoryButtonPushedForRowAtIndexPath:(NSIndexPath *)indexPath;
Run Code Online (Sandbox Code Playgroud)

他们非常自我解释.

  • Apple已经在iOS 8中打开了这个功能.请参阅下面的Johnny的回答. (4认同)

Aru*_*Das 24

为了改进Johnny的答案,现在可以使用公共API完成此操作,如下所示:

func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {

    let moreRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "More", handler:{action, indexpath in
        print("MORE•ACTION");
    });
    moreRowAction.backgroundColor = UIColor(red: 0.298, green: 0.851, blue: 0.3922, alpha: 1.0);

    let deleteRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "Delete", handler:{action, indexpath in
        print("DELETE•ACTION");
    });

    return [deleteRowAction, moreRowAction];
}
Run Code Online (Sandbox Code Playgroud)


Dee*_*yan 17

我希望你不能等到苹果给你什么,你需要什么?所以这是我的选择.

创建自定义单元格.有两个uiviews

1. upper
2. lower
Run Code Online (Sandbox Code Playgroud)

在下方视图中,添加您需要的按钮.像任何其他IBActions一样处理其行为.你可以决定动画的时间,风格和任何东西.

现在在上方视图中添加一个uiswipegesture,并在滑动手势上显示您的下方视图.我以前做过这个,就我而言,它是最简单的选择.

希望有所帮助.


Ort*_*ntz 7

使用标准SDK无法做到这一点.但是,有各种第三方解决方案或多或少地模仿Mail.app中的行为.其中一些(例如MCSwipeTableViewCell,DAContextMenuTableViewController,RMSwipeTableViewCell)使用手势识别器检测滑动,其中一些(例如SWTableViewCell)将第二个UISScrollView放在标准UITableViewCellScrollView(私有子视图UITableViewCell)之下,其中一些修改了它们的行为UITableViewCellScrollView.

我最喜欢最后一种方法,因为触摸处理感觉最自然.具体来说,MSCMoreOptionTableViewCell很好.您的选择可能会根据您的具体需求而有所不同(无论您是否需要从左到右的平底锅,是否需要iOS 6兼容性等).还要注意,大多数这些方法都有负担:如果Apple在UITableViewCell子视图层次结构中进行更改,它们很容易在未来的iOS版本中中断.


mri*_*011 7

Swift 3版本代码,不使用任何库:

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        tableView.tableFooterView = UIView(frame: CGRect.zero) //Hiding blank cells.
        tableView.separatorInset = UIEdgeInsets.zero
        tableView.dataSource = self
        tableView.delegate = self
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return 4
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath)

        return cell
    }

    //Enable cell editing methods.
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {

        return true
    }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {

    }

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {

        let more = UITableViewRowAction(style: .normal, title: "More") { action, index in
            //self.isEditing = false
            print("more button tapped")
        }
        more.backgroundColor = UIColor.lightGray

        let favorite = UITableViewRowAction(style: .normal, title: "Favorite") { action, index in
            //self.isEditing = false
            print("favorite button tapped")
        }
        favorite.backgroundColor = UIColor.orange

        let share = UITableViewRowAction(style: .normal, title: "Share") { action, index in
            //self.isEditing = false
            print("share button tapped")
        }
        share.backgroundColor = UIColor.blue

        return [share, favorite, more]
    }

}
Run Code Online (Sandbox Code Playgroud)


Kha*_*yen 6

您需要子类化UITableViewCell和子类化方法willTransitionToState:(UITableViewCellStateMask)state,只要用户刷新单元格就会调用该方法.该state标志将让你知道,如果删除按钮被显示,并显示/隐藏您的更多按钮那里.

不幸的是,这种方法既不提供删除按钮的宽度也不提供动画时间.因此,您需要观察并将您的更多按钮的帧和动画时间硬编码到您的代码中(我个人认为Apple需要对此做些什么).

  • "我个人认为Apple需要对此做些什么".我同意.你有没有给他们写错误报告/功能请求? (7认同)

Lew*_*s42 5

从 iOS 11 开始,这在UITableViewDelegate. 这是一些示例代码:

迅速

func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {

    let action = UIContextualAction(style: .normal, title: nil) { (_, _, _) in
        print("Swipe action tapped")
    }

    action.image = UIImage(systemName: "plus.slash.minus")
    action.backgroundColor = .green

    return UISwipeActionsConfiguration(actions: [action])
}
Run Code Online (Sandbox Code Playgroud)

目标C

- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath {
    UIContextualAction *delete = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive
                                                                         title:@"DELETE"
                                                                       handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
                                                                           NSLog(@"index path of delete: %@", indexPath);
                                                                           completionHandler(YES);
                                                                       }];

    UIContextualAction *rename = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleNormal
                                                                         title:@"RENAME"
                                                                       handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) {
                                                                           NSLog(@"index path of rename: %@", indexPath);
                                                                           completionHandler(YES);
                                                                       }];

    UISwipeActionsConfiguration *swipeActionConfig = [UISwipeActionsConfiguration configurationWithActions:@[rename, delete]];
    swipeActionConfig.performsFirstActionWithFullSwipe = NO;

    return swipeActionConfig;
}
Run Code Online (Sandbox Code Playgroud)

也提供:

- (UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath;

文档:https://developer.apple.com/documentation/uikit/uitableviewdelegate/2902367-tableview ?language=objc