简体   繁体   English

iOS - 如何查看表格视图单元格上的“滑动删除”操作?

[英]iOS - How To Give A Peek At The "Swipe To Delete" Action On A Table View Cell?

When a certain Table View Controller displays for the first time, how to briefly show that the red “swipe to delete” functionality exists in a table row?当某个Table View Controller第一次显示时,如何简单的显示一个表格行中存在红色的“滑动删除”功能?

The goal of programmatically playing peekaboo with this is to show the user that the functionality exists.以编程方式玩躲猫猫的目的是向用户展示该功能的存在。

Environment: iOS 11+ and iPhone app.环境:iOS 11+ 和 iPhone 应用程序。

Here's an image showing the cell slid partway with a basic "swipe to delete" red action button.这是一张图像,显示单元格滑动到一半,带有一个基本的“滑动删除”红色操作按钮。 通过部分滑动显示表格单元格下的删除操作

A fellow developer kindly mentioned SwipeCellKit, but there's a lot to SwipeCellKit.一位开发人员友好地提到了 SwipeCellKit,但 SwipeCellKit 有很多。 All we want to do is briefly simulate a partial swipe to let the user know the "swipe to delete" exists.我们想要做的只是简单地模拟部分滑动,让用户知道“滑动删除”的存在。 In other words, we want to provide a sneak peak at the delete action under the cell.换句话说,我们希望在单元格下的删除操作中提供一个潜行高峰。

In case it helps, here's the link to the SwipeCellKit's showSwipe code Here is a link with an example of its use .如果它有帮助,这里是SwipeCellKit 的showSwipe代码链接这里是一个包含其使用示例的链接

I looked at the SwipeCellKit source code.我查看了 SwipeCellKit 源代码。 It's not clear to me how to do it without SwipeCellKit.我不清楚如何在没有 SwipeCellKit 的情况下做到这一点。 Also, Using SwipeCellKit is not currently an option.此外,目前还不能选择使用 SwipeCellKit。

Googling hasn't helped.谷歌搜索没有帮助。 I keep running into how to add swipe actions , but not how to briefly show the Swipe Actions aka UITableViewRowAction items that are under the cell to the user.我一直在研究如何添加滑动操作,但没有研究如何向用户简要显示单元格下的滑动操作,即 UITableViewRowAction 项目。

How to briefly show this built in "swipe to delete" action to the user?如何向用户简要显示这个内置的“滑动删除”操作?

I've written this simple extension for UITableView .我已经为UITableView编写了这个简单的扩展。 It searches through visible cells, finds first row that contains edit actions and then performs the magic.它搜索可见单元格,找到包含编辑操作的第一行,然后执行魔术。 You can adjust parameters like width and duration of the hint.您可以调整提示的宽度和持续时间等参数。

It works great because it doesn't hardcode any values, so for example the hint's background color will always match the real action button.它工作得很好,因为它不硬编码任何值,因此例如提示的背景颜色将始终与实际操作按钮匹配。

import UIKit

extension UITableView {
    /**
     Shows a hint to the user indicating that cell can be swiped left.
     - Parameters:
        - width: Width of hint.
        - duration: Duration of animation (in seconds)
     */
    func presentTrailingSwipeHint(width: CGFloat = 20, duration: TimeInterval = 0.8) {
        var actionPath: IndexPath?
        var actionColor: UIColor?
        
        guard let visibleIndexPaths = indexPathsForVisibleRows else {
            return
        }
        if #available(iOS 13.0, *) {
            // Use new API, UIContextualAction
            for path in visibleIndexPaths {
                if let config = delegate?.tableView?(self, trailingSwipeActionsConfigurationForRowAt: path), let action = config.actions.first {
                    actionPath = path
                    actionColor = action.backgroundColor
                    break
                }
            }
        } else {
            for path in visibleIndexPaths {
                if let actions = delegate?.tableView?(self, editActionsForRowAt: path), let action = actions.first {
                    actionPath = path
                    actionColor = action.backgroundColor
                    break
                }
            }
        }
        guard let path = actionPath, let cell = cellForRow(at: path) else { return }
        cell.presentTrailingSwipeHint(actionColor: actionColor ?? tintColor)
    }
}

fileprivate extension UITableViewCell {
    func presentTrailingSwipeHint(actionColor: UIColor, hintWidth: CGFloat = 20, hintDuration: TimeInterval = 0.8) {
        // Create fake action view
        let dummyView = UIView()
        dummyView.backgroundColor = actionColor
        dummyView.translatesAutoresizingMaskIntoConstraints = false
        addSubview(dummyView)
        // Set constraints
        NSLayoutConstraint.activate([
            dummyView.topAnchor.constraint(equalTo: topAnchor),
            dummyView.leadingAnchor.constraint(equalTo: trailingAnchor),
            dummyView.bottomAnchor.constraint(equalTo: bottomAnchor),
            dummyView.widthAnchor.constraint(equalToConstant: hintWidth)
        ])
        // This animator reverses back the transform.
        let secondAnimator = UIViewPropertyAnimator(duration: hintDuration / 2, curve: .easeOut) {
            self.transform = .identity
        }
        // Don't forget to remove the useless view.
        secondAnimator.addCompletion { position in
            dummyView.removeFromSuperview()
        }

        // We're moving the cell and since dummyView
        // is pinned to cell's trailing anchor
        // it will move as well.
        let transform = CGAffineTransform(translationX: -hintWidth, y: 0)
        let firstAnimator = UIViewPropertyAnimator(duration: hintDuration / 2, curve: .easeIn) {
            self.transform = transform
        }
        firstAnimator.addCompletion { position in
            secondAnimator.startAnimation()
        }
        // Do the magic.
        firstAnimator.startAnimation()
    }
}

Example usage:用法示例:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    tableView.presentSwipeHint()
}

在此处输入图片说明

I'm pretty sure this can't be done.我很确定这是做不到的。 The swipe actions are contained in a UISwipeActionPullView , which contains UISwipeStandardAction subviews, both of which are private.滑动操作包含在UISwipeActionPullView ,它包含UISwipeStandardAction子视图,两者都是私有的。 They are also part of the table view, not the cell, and they're not added unless a gesture is happening, so you can't just bump the cell to one side and see them there.它们也是表格视图的一部分,而不是单元格,除非发生手势,否则不会添加它们,因此您不能只是将单元格撞到一侧并在那里看到它们。

Outside of UI automation tests, it isn't possible to simulate user gestures without using private API, so you can't "fake" a swipe and then show the results to the user.在 UI 自动化测试之外,不使用私有 API 就无法模拟用户手势,因此您无法“伪造”滑动然后将结果显示给用户。

However, why bother doing it "properly" when you can cheat?但是,当您可以作弊时,为什么还要“正确”地做呢? It shouldn't be too hard to bounce the cell's content view slightly to the left, and bounce in a red box (not so far that you can see text, to avoid localisation issues), then return to normal.将单元格的内容视图稍微向左弹跳应该不会太难,并在红色框中弹跳(不要远到您可以看到文本,以避免本地化问题),然后恢复正常。 Do this on the first load of the table view, and stop doing it after N times or after the user has proven that they know how this particular iOS convention works.在第一次加载 table view 时执行此操作,并在 N 次后或在用户证明他们知道此特定 iOS 约定如何工作后停止执行此操作。

First : enable the editing第一:启用编辑

func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
   return true
}

Then customise your swipe然后自定义您的滑动

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
   let conformeRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: NSLocalizedString("C", comment: ""), handler:{action, indexpath in
        print("C•ACTION")
    })
   conformeRowAction.backgroundColor = UIColor(red: 154.0/255, green: 202.0/255, blue: 136.0/255, alpha: 1.0)
   let notConform = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: NSLocalizedString("NC", comment: ""), handler:{action, indexpath in
        print("NC•ACTION")
    })
   notConform.backgroundColor = UIColor(red: 252.0/255, green: 108.0/255, blue: 107.0/255, alpha: 1.0)
   return [conformeRowAction,notConform]
}

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

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