iOS - 如何查看 "Swipe To Delete" 视图单元格上的 "Swipe To Delete" 操作?
iOS - How To Give A Peek At The "Swipe To Delete" Action On A Table View Cell?
当某个Table View Controller 第一次显示时,如何简单地显示table 行中存在红色的“滑动删除”功能?
以编程方式玩躲猫猫的目的是向用户展示该功能的存在。
环境:iOS 11+ 和 iPhone 应用程序。
这是一张显示单元格滑动到一半的图片,带有基本的 "swipe to delete" 红色操作按钮。
一位开发人员友善地提到了 SwipeCellKit,但 SwipeCellKit 的功能很多。我们想要做的只是简单地模拟部分滑动,让用户知道 "swipe to delete" 存在。换句话说,我们希望在单元格下的删除操作中提供先睹为快。
如果有帮助,这里是 link 到 SwipeCellKit's showSwipe
code Here is a link with an example of its use。
我查看了 SwipeCellKit 源代码。我不清楚如何在没有 SwipeCellKit 的情况下进行操作。此外,目前无法使用 SwipeCellKit。
谷歌搜索没有帮助。我将 运行 保留为 how to add swipe actions,但没有向用户简要显示单元格下的滑动操作又名 UITableViewRowAction 项。
如何向用户简要显示此内置 "swipe to delete" 操作?
首先 : 启用编辑
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
然后自定义滑动
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]
}
我很确定这是不可能的。滑动操作包含在 UISwipeActionPullView
中,其中包含 UISwipeStandardAction
个子视图,它们都是私有的。它们也是 table 视图的一部分,而不是单元格的一部分,除非发生手势,否则不会添加它们,因此您不能只是将单元格撞到一侧并在那里看到它们。
在 UI 自动化测试之外,不使用私有 API 就无法模拟用户手势,因此您无法 "fake" 滑动然后显示结果给用户。
但是,既然可以作弊,为什么还要这样做 "properly"?将单元格的内容视图稍微向左弹跳,并在红色框中弹跳(不要太远,你可以看到文本,以避免本地化问题)应该不会太难,然后 return 恢复正常。在 table 视图的第一次加载时执行此操作,并在 N 次后或在用户证明他们知道此特定 iOS 约定如何工作后停止执行此操作。
我为 UITableView
编写了这个简单的扩展。它搜索可见单元格,找到包含编辑操作的第一行,然后执行魔术。您可以调整提示的宽度和持续时间等参数。
效果很好,因为它不会对任何值进行硬编码,例如,提示的背景颜色将始终与实际操作按钮相匹配。
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()
}
}
用法示例:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
tableView.presentSwipeHint()
}
当某个Table View Controller 第一次显示时,如何简单地显示table 行中存在红色的“滑动删除”功能?
以编程方式玩躲猫猫的目的是向用户展示该功能的存在。
环境:iOS 11+ 和 iPhone 应用程序。
这是一张显示单元格滑动到一半的图片,带有基本的 "swipe to delete" 红色操作按钮。
一位开发人员友善地提到了 SwipeCellKit,但 SwipeCellKit 的功能很多。我们想要做的只是简单地模拟部分滑动,让用户知道 "swipe to delete" 存在。换句话说,我们希望在单元格下的删除操作中提供先睹为快。
如果有帮助,这里是 link 到 SwipeCellKit's showSwipe
code Here is a link with an example of its use。
我查看了 SwipeCellKit 源代码。我不清楚如何在没有 SwipeCellKit 的情况下进行操作。此外,目前无法使用 SwipeCellKit。
谷歌搜索没有帮助。我将 运行 保留为 how to add swipe actions,但没有向用户简要显示单元格下的滑动操作又名 UITableViewRowAction 项。
如何向用户简要显示此内置 "swipe to delete" 操作?
首先 : 启用编辑
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
然后自定义滑动
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]
}
我很确定这是不可能的。滑动操作包含在 UISwipeActionPullView
中,其中包含 UISwipeStandardAction
个子视图,它们都是私有的。它们也是 table 视图的一部分,而不是单元格的一部分,除非发生手势,否则不会添加它们,因此您不能只是将单元格撞到一侧并在那里看到它们。
在 UI 自动化测试之外,不使用私有 API 就无法模拟用户手势,因此您无法 "fake" 滑动然后显示结果给用户。
但是,既然可以作弊,为什么还要这样做 "properly"?将单元格的内容视图稍微向左弹跳,并在红色框中弹跳(不要太远,你可以看到文本,以避免本地化问题)应该不会太难,然后 return 恢复正常。在 table 视图的第一次加载时执行此操作,并在 N 次后或在用户证明他们知道此特定 iOS 约定如何工作后停止执行此操作。
我为 UITableView
编写了这个简单的扩展。它搜索可见单元格,找到包含编辑操作的第一行,然后执行魔术。您可以调整提示的宽度和持续时间等参数。
效果很好,因为它不会对任何值进行硬编码,例如,提示的背景颜色将始终与实际操作按钮相匹配。
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()
}
}
用法示例:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
tableView.presentSwipeHint()
}