首页 文章

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

提问于
浏览
237

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

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

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

enter image description here

20 回答

  • 123

    如何实施

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

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

    - tableView:editActionsForRowAtIndexPath:
    - tableView:commitEditingStyle:forRowAtIndexPath:
    

    已知问题

    文档说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];
    }
    
  • 3

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

    https://github.com/MortimerGoro/MGSwipeTableCell

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

    这里有一些过渡的样本:

    边境过渡:

    Border transition

    剪辑转换

    Clip transition

    3D过渡:

    enter image description here

  • 4

    约翰尼的回答是正确的回答 . 我只是在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...
        }
    
  • 3

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

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

    -(NSString *)tableView:(UITableView *)tableView titleForSwipeAccessoryButtonForRowAtIndexPath:(NSIndexPath *)indexPath;
    -(void)tableView:(UITableView *)tableView swipeAccessoryButtonPushedForRowAtIndexPath:(NSIndexPath *)indexPath;
    

    他们非常自我解释 .

  • 1

    为了改进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];
    }
    
  • 6

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

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

    1. upper
    2. lower
    

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

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

    希望有所帮助 .

  • 68

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

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

  • 3

    Swift 3 version code without using any library:

    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]
        }
    
    }
    
  • 25

    您需要子类化 UITableViewCell 和子类方法 willTransitionToState:(UITableViewCellStateMask)state ,只要用户滑动单元格就会调用它 . 如果显示“删除”按钮, state 标志将通知您,并在那里显示/隐藏“更多”按钮 .

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

  • 23

    用于快速编程

    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
      if editingStyle == UITableViewCellEditingStyle.Delete {
        deleteModelAt(indexPath.row)
        self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
      }
      else if editingStyle == UITableViewCellEditingStyle.Insert {
        println("insert editing action")
      }
    }
    
    func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {
      var archiveAction = UITableViewRowAction(style: .Default, title: "Archive",handler: { (action: UITableViewRowAction!, indexPath: NSIndexPath!) in
            // maybe show an action sheet with more options
            self.tableView.setEditing(false, animated: false)
          }
      )
      archiveAction.backgroundColor = UIColor.lightGrayColor()
    
      var deleteAction = UITableViewRowAction(style: .Normal, title: "Delete",
          handler: { (action: UITableViewRowAction!, indexPath: NSIndexPath!) in
            self.deleteModelAt(indexPath.row)
            self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic);
          }
      );
      deleteAction.backgroundColor = UIColor.redColor()
    
      return [deleteAction, archiveAction]
    }
    
    func deleteModelAt(index: Int) {
      //... delete logic for model
    }
    
  • 3

    这可以帮助你OUT .

    -(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...
        }
    
  • 7

    我想在我的应用程序中添加相同的功能,经过这么多不同的教程(raywenderlich是最好的DIY解决方案)之后,我发现Apple有自己的 UITableViewRowAction 类,这非常方便 .

    您必须将Tableview的boilerpoint方法更改为:

    override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]?  {
        // 1   
        var shareAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Share" , handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in
        // 2
        let shareMenu = UIAlertController(title: nil, message: "Share using", preferredStyle: .ActionSheet)
    
        let twitterAction = UIAlertAction(title: "Twitter", style: UIAlertActionStyle.Default, handler: nil)
        let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)
    
        shareMenu.addAction(twitterAction)
        shareMenu.addAction(cancelAction)
    
    
        self.presentViewController(shareMenu, animated: true, completion: nil)
        })
        // 3
        var rateAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Rate" , handler: { (action:UITableViewRowAction!, indexPath:NSIndexPath!) -> Void in
        // 4
        let rateMenu = UIAlertController(title: nil, message: "Rate this App", preferredStyle: .ActionSheet)
    
        let appRateAction = UIAlertAction(title: "Rate", style: UIAlertActionStyle.Default, handler: nil)
        let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil)
    
        rateMenu.addAction(appRateAction)
        rateMenu.addAction(cancelAction)
    
    
        self.presentViewController(rateMenu, animated: true, completion: nil)
        })
        // 5
        return [shareAction,rateAction]
      }
    

    您可以在This Site上找到更多相关信息 . Apple的own documentation对于更改背景颜色非常有用:

    动作按钮的背景颜色 . 声明OBJECTIVE-C @property(非原子,复制)UIColor * backgroundColor讨论使用此属性指定按钮的背景颜色 . 如果未指定此属性的值,UIKit将根据style属性中的值指定默认颜色 . 可用性适用于iOS 8.0及更高版本 .

    如果你想改变按钮的字体,那么's a bit more tricky. I'已经在SO上看到了another post . 为了提供代码和链接,这里's the code they used there. You' d必须改变按钮的外观 . 你'd have to make a specific reference to tableviewcell, otherwise you' d改变按钮's appearance throughout your app (I didn' t想要那个,但你可能,我不知道:))

    目标C:

    + (void)setupDeleteRowActionStyleForUserCell {
    
        UIFont *font = [UIFont fontWithName:@"AvenirNext-Regular" size:19];
    
        NSDictionary *attributes = @{NSFontAttributeName: font,
                          NSForegroundColorAttributeName: [UIColor whiteColor]};
    
        NSAttributedString *attributedTitle = [[NSAttributedString alloc] initWithString: @"DELETE"
                                                                              attributes: attributes];
    
        /*
         * We include UIView in the containment hierarchy because there is another button in UserCell that is a direct descendant of UserCell that we don't want this to affect.
         */
        [[UIButton appearanceWhenContainedIn:[UIView class], [UserCell class], nil] setAttributedTitle: attributedTitle
                                                                                              forState: UIControlStateNormal];
    }
    

    迅速:

    //create your attributes however you want to
        let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(UIFont.systemFontSize())] as Dictionary!            
    
       //Add more view controller types in the []
        UIButton.appearanceWhenContainedInInstancesOfClasses([ViewController.self])
    

    这是最简单,最流线型的版本恕我直言 . 希望能帮助到你 .

    更新:这是Swift 3.0版本:

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        var shareAction:UITableViewRowAction = UITableViewRowAction(style: .default, title: "Share", handler: {(action, cellIndexpath) -> Void in
            let shareMenu = UIAlertController(title: nil, message: "Share using", preferredStyle: .actionSheet)
    
            let twitterAction = UIAlertAction(title: "Twitter", style: .default, handler: nil)
            let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
    
            shareMenu.addAction(twitterAction)
            shareMenu.addAction(cancelAction)
    
    
            self.present(shareMenu,animated: true, completion: nil)
        })
    
        var rateAction:UITableViewRowAction = UITableViewRowAction(style: .default, title: "Rate" , handler: {(action, cellIndexpath) -> Void in
            // 4
            let rateMenu = UIAlertController(title: nil, message: "Rate this App", preferredStyle: .actionSheet)
    
            let appRateAction = UIAlertAction(title: "Rate", style: .default, handler: nil)
            let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
    
            rateMenu.addAction(appRateAction)
            rateMenu.addAction(cancelAction)
    
    
            self.present(rateMenu, animated: true, completion: nil)
        })
        // 5
        return [shareAction,rateAction]
    }
    
  • 17

    Actual Swift 3 Answer

    这是您需要的唯一功能 . 您不需要CanEdit或CommitEditingStyle函数来执行自定义操作 .

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        let action1 = UITableViewRowAction(style: .default, title: "Action1", handler: {
            (action, indexPath) in
            print("Action1")
        })
        action1.backgroundColor = UIColor.lightGray
        let action2 = UITableViewRowAction(style: .default, title: "Action2", handler: {
            (action, indexPath) in
            print("Action2")
        })
        return [action1, action2]
    }
    
  • 1

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

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

    也提供:

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

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

  • 118

    Swift 4&iOs 11

    @available(iOS 11.0, *)
    override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
    
        let delete = UIContextualAction(style: .destructive, title: "Delete") { _, _, handler in
    
            handler(true)
            // handle deletion here
        }
    
        let more = UIContextualAction(style: .normal, title: "More") { _, _, handler in
    
            handler(true)
            // handle more here
        }
    
        return UISwipeActionsConfiguration(actions: [delete, more])
    }
    
  • 7

    这是一种有点脆弱的方式,不涉及私有API或构建自己的系统 . 你正在对冲苹果公司没有打破这一点的赌注,希望他们能够发布一个API,你可以用这几行代码代替 .

    • KVO self.contentView.superview.layer.sublayer. 在init中执行此操作 . 这是UIScrollView 's layer. You can' t KVO 'subviews' .

    • When subviews changes, find the delete confirmation view within scrollview.subviews. 这是在observe回调中完成的 .

    • Double the size of that view and add a UIButton to the left of its only subview. 这也是在observe回调中完成的 . 删除确认视图的唯一子视图是删除按钮 .

    • (可选)UIButton事件应查找self.superview,直到找到UITableView,然后调用您创建的数据源或委托方法,例如tableView:commitCustomEditingStyle:forRowAtIndexPath: . 您可以使用[tableView indexPathForCell:self]找到单元格的indexPath .

    这还要求您实现标准表视图编辑委托回调 .

    static char kObserveContext = 0;
    
    @implementation KZTableViewCell {
        UIScrollView *_contentScrollView;
        UIView *_confirmationView;
        UIButton *_editButton;
        UIButton *_deleteButton;
    }
    
    - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
        self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
        if (self) {
            _contentScrollView = (id)self.contentView.superview;
    
            [_contentScrollView.layer addObserver:self
                 forKeyPath:@"sublayers"
                    options:0
                    context:&kObserveContext];
    
            _editButton = [UIButton new];
            _editButton.backgroundColor = [UIColor lightGrayColor];
            [_editButton setTitle:@"Edit" forState:UIControlStateNormal];
            [_editButton addTarget:self
                            action:@selector(_editTap)
                  forControlEvents:UIControlEventTouchUpInside];
    
        }
        return self;
    }
    
    -(void)dealloc {
        [_contentScrollView.layer removeObserver:self forKeyPath:@"sublayers" context:&kObserveContext];
    }
    
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
        if(context != &kObserveContext) {
            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
            return;
        }
        if(object == _contentScrollView.layer) {
            for(UIView * view in _contentScrollView.subviews) {
                if([NSStringFromClass(view.class) hasSuffix:@"ConfirmationView"]) {
                    _confirmationView = view;
                    _deleteButton = [view.subviews objectAtIndex:0];
                    CGRect frame = _confirmationView.frame;
                    CGRect frame2 = frame;
                    frame.origin.x -= frame.size.width;
                    frame.size.width *= 2;
                    _confirmationView.frame = frame;
    
                    frame2.origin = CGPointZero;
                    _editButton.frame = frame2;
                    frame2.origin.x += frame2.size.width;
                    _deleteButton.frame = frame2;
                    [_confirmationView addSubview:_editButton];
                    break;
                }
            }
            return;
        }
    }
    
    -(void)_editTap {
        UITableView *tv = (id)self.superview;
        while(tv && ![tv isKindOfClass:[UITableView class]]) {
            tv = (id)tv.superview;
        }
        id<UITableViewDelegate> delegate = tv.delegate;
        if([delegate respondsToSelector:@selector(tableView:editTappedForRowWithIndexPath:)]) {
            NSIndexPath *ip = [tv indexPathForCell:self];
            // define this in your own protocol
            [delegate tableView:tv editTappedForRowWithIndexPath:ip];
        }
    }
    @end
    
  • 3

    有一个名为 SwipeCellKit 的惊人库,它应该获得更多的认可 . 在我看来,它比 MGSwipeTableCell 更酷 . 后者不是't completely replicate the behavior of the Mail app'的细胞而 SwipeCellKit . Have a look

  • 1

    Swift 4

    func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        let delete = UIContextualAction(style: .destructive, title: "Delete") { (action, sourceView, completionHandler) in
            print("index path of delete: \(indexPath)")
            completionHandler(true)
        }
        let rename = UIContextualAction(style: .normal, title: "Edit") { (action, sourceView, completionHandler) in
            print("index path of edit: \(indexPath)")
            completionHandler(true)
        }
        let swipeActionConfig = UISwipeActionsConfiguration(actions: [rename, delete])
        swipeActionConfig.performsFirstActionWithFullSwipe = false
        return swipeActionConfig
    }
    
  • 0

    我使用 tableViewCell 来显示多个数据,在一个单元格上向右滑动()后会显示两个按钮Approve和reject,有两个方法,第一个是ApproveFunc,它接受一个参数,另一个是RejectFunc,它也是有一个论点 .

    enter image description here

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
            let Approve = UITableViewRowAction(style: .normal, title: "Approve") { action, index in
    
                self.ApproveFunc(indexPath: indexPath)
            }
            Approve.backgroundColor = .green
    
            let Reject = UITableViewRowAction(style: .normal, title: "Reject") { action, index in
    
                self.rejectFunc(indexPath: indexPath)
            }
            Reject.backgroundColor = .red
    
    
    
            return [Reject, Approve]
        }
    
        func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
            return true
        }
    
        func ApproveFunc(indexPath: IndexPath) {
            print(indexPath.row)
        }
        func rejectFunc(indexPath: IndexPath) {
            print(indexPath.row)
        }
    
  • 1

    这是一个简单的解决方案 . 它能够在UITableViewCell中显示和隐藏自定义UIView . 显示逻辑包含在从UITableViewCell,BaseTableViewCell扩展的类中 .

    BaseTableViewCell.h

    #import <UIKit/UIKit.h>
    
    @interface BaseTableViewCell : UITableViewCell
    
    @property(nonatomic,strong)UIView* customView;
    
    -(void)showCustomView;
    
    -(void)hideCustomView;
    
    @end
    

    BaseTableViewCell.M

    #import "BaseTableViewCell.h"
    
    @interface BaseTableViewCell()
    {
        BOOL _isCustomViewVisible;
    }
    
    @end
    
    @implementation BaseTableViewCell
    
    - (void)awakeFromNib {
        // Initialization code
    }
    
    -(void)prepareForReuse
    {
        self.customView = nil;
        _isCustomViewVisible = NO;
    }
    
    - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
        [super setSelected:selected animated:animated];
    
        // Configure the view for the selected state
    }
    
    -(void)showCustomView
    {
        if(nil != self.customView)
        {
            if(!_isCustomViewVisible)
            {
                _isCustomViewVisible = YES;
    
                if(!self.customView.superview)
                {
                    CGRect frame = self.customView.frame;
                    frame.origin.x = self.contentView.frame.size.width;
                    self.customView.frame = frame;
                    [self.customView willMoveToSuperview:self.contentView];
                    [self.contentView addSubview:self.customView];
                    [self.customView didMoveToSuperview];
                }
    
                __weak BaseTableViewCell* blockSelf = self;
                [UIView animateWithDuration:.5 animations:^(){
    
                    for(UIView* view in blockSelf.contentView.subviews)
                    {
                        CGRect frame = view.frame;
                        frame.origin.x = frame.origin.x - blockSelf.customView.frame.size.width;
                        view.frame = frame;
                    }
                }];
            }
        }
    }
    
    -(void)hideCustomView
    {
        if(nil != self.customView)
        {
            if(_isCustomViewVisible)
            {
                __weak BaseTableViewCell* blockSelf = self;
                _isCustomViewVisible = NO;
                [UIView animateWithDuration:.5 animations:^(){
                    for(UIView* view in blockSelf.contentView.subviews)
                    {
                        CGRect frame = view.frame;
                        frame.origin.x = frame.origin.x + blockSelf.customView.frame.size.width;
                        view.frame = frame;
                    }
                }];
            }
        }
    }
    
    @end
    

    要获得此功能,只需从BaseTableViewCell扩展表视图单元 .

    接下来,实现UITableViewDelegate的Inside UIViewController创建了两个手势识别器来处理左右滑动 .

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
    
        [self.tableView registerNib:[UINib nibWithNibName:CUSTOM_CELL_NIB_NAME bundle:nil] forCellReuseIdentifier:CUSTOM_CELL_ID];
    
        UISwipeGestureRecognizer* leftSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleLeftSwipe:)];
        leftSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
        [self.tableView addGestureRecognizer:leftSwipeRecognizer];
    
        UISwipeGestureRecognizer* rightSwipeRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleRightSwipe:)];
        rightSwipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
        [self.tableView addGestureRecognizer:rightSwipeRecognizer];
    }
    

    比添加两个滑动处理程序

    - (void)handleLeftSwipe:(UISwipeGestureRecognizer*)recognizer
    {
        CGPoint point = [recognizer locationInView:self.tableView];
        NSIndexPath* index = [self.tableView indexPathForRowAtPoint:point];
    
        UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:index];
    
        if([cell respondsToSelector:@selector(showCustomView)])
        {
            [cell performSelector:@selector(showCustomView)];
        }
    }
    
    - (void)handleRightSwipe:(UISwipeGestureRecognizer*)recognizer
    {
        CGPoint point = [recognizer locationInView:self.tableView];
        NSIndexPath* index = [self.tableView indexPathForRowAtPoint:point];
    
        UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:index];
    
        if([cell respondsToSelector:@selector(hideCustomView)])
        {
            [cell performSelector:@selector(hideCustomView)];
        }
    }
    

    现在,在UITableViewDelegate的cellForRowAtIndexPath中,您可以创建自定义UIView并将其附加到出列单元格 .

    -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        CustomCellTableViewCell* cell = (CustomCellTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"CustomCellTableViewCell" forIndexPath:indexPath];
    
        NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:@"CellCustomView"
                                                          owner:nil
                                                        options:nil];
    
        CellCustomView* customView = (CellCustomView*)[ nibViews objectAtIndex: 0];
    
        cell.customView = customView;
    
        return cell;
    }
    

    当然,这种加载自定义UIView的方式仅适用于此示例 . 根据需要管理它 .

相关问题