长按时像 iMessage 一样突出显示 UITableViewCell

Posted

技术标签:

【中文标题】长按时像 iMessage 一样突出显示 UITableViewCell【英文标题】:Highlight UITableViewCell like iMessage when long pressed 【发布时间】:2019-02-11 10:03:47 【问题描述】:

我使用UITableView 创建了简单的聊天。我想添加长按后突出显示消息的功能。事实上,我想创建和 iMessage 一样的功能:

长按后,我们取消突出显示背景(更暗),突出显示消息,滚动到此消息并显示actionSheet

目前我只添加了longPressactionSheet

viewDidLoad 上的长按识别器:

let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(onCellLongPressed(gesture:)))
messagesTableView.addGestureRecognizer(longPressRecognizer)

onCellLongPressed函数:

@objc func onCellLongPressed(gesture: UILongPressGestureRecognizer) 

    if gesture.state == UIGestureRecognizerState.began 
        let touchPoint = gesture.location(in: self.messagesTableView)
        if let indexPath = messagesTableView.indexPathForRow(at: touchPoint) 
            self.messagesTableView.selectRow(at: indexPath, animated: true, scrollPosition: UITableViewScrollPosition.none)
            shareWithFriend()
        
    


@objc func shareWithFriend() 
    alert(style: .actionSheet, actions: [
        UIAlertAction(title: "Share with friend", style: .default, handler:  [weak self] (_) in
            print("SHARE HERE")
        ),
        UIAlertAction(title: "Cancel", style: .destructive),
        ])


func alert(_ title: String? = nil, message: String? = nil, style: UIAlertController.Style, actions: [UIAlertAction]) 
    let alertController = UIAlertController(title: title, message: message, preferredStyle: style)
    actions.forEach(alertController.addAction)
    present(alertController, animated: true)

【问题讨论】:

关于滚动,我建议使用以下代码: tableView?.scrollToRow(at: [0,0], at: UITableViewScrollPosition.top, animated: true) 只需将 [0,0] 替换为索引路径 @DJ-Glock 谢谢!突出显示选定的单元格呢? 让我检查一下我的代码。我已经实现了类似的东西。 我已经发布了我的答案。请注意,我没有对其进行测试,但希望对您有所帮助。 我做了一些更新。感谢您的反馈。 【参考方案1】:

如您所见,背景颜色在导航栏上方,所以我猜当用户选择单元格时,集合视图上方巧妙地呈现了一个辅助视图控制器。

我认为这是两个不同的视图层次结构,它们看起来像一个:

一个视图控制器包含气球列表 一个视图控制器包含所选气球的副本以及与之关联的一些操作

这是路线图:

    检测集合视图单元格中的长按 复制选定的气球并将其显示在辅助视图控制器 (ActionVC) 中 调整所选气球在 ActionVC 内的位置。如果选定的气球在未来的行动按钮下,它应该被移动。如果所选气球不会打扰任何人,则应原样显示。 调整集合视图的内容偏移以反映 3。修改应与 3 一起进行,以使单元格看起来像实际移动了。 检测 ActionVC 上的任何触摸 关闭 ActionVC

这是example project。

为了复制气球,我实际上创建了一个与集合视图单元格中使用的类相同的视图。但您可以使用快照。 为了调整 ActionVC 中选定的气球位置,我使用了带优先级的约束。一个声称“不要在操作按钮下”,另一个声称“正好在牢房所在的位置”。我使用简单的坐标转换来计算 ActionVC 中预期的选定气球位置。 为了在 4 旁边执行 3,我使用了 ActionVC 的 transitionCoordinator,但您可以使用简单的动画块并在没有动画的情况下呈现 ActionVC。

【讨论】:

感谢您的出色解决方案!如何调整顶部的气球位置? 不客气@DenAndreychuk。与底部情况一样,添加顶部约束并在气球移动时调整偏移量。 太棒了。你认为他们对按钮使用自定义类吗?现在我在考虑行动表。这是个好主意吗? 使用警报表不起作用,因为您无法确定按钮的大小。重新创建它:一个 UIButton + 一个 UIVisualEffectView。【参考方案2】:

如果这个答案不能完全满足您的要求,我很抱歉,但希望它对您有所帮助。

您的初始代码是正确的,但您没有设置滚动类型。所以我建议你使用这种方法selectRow(at:animated:scrollPosition:)只需设置滚动位置:

self.messagesTableView.selectRow(at: indexPath, animated: true, scrollPosition: UITableViewScrollPosition.top)

这也将选择这一行并因此调用以下方法tableView(_:didSelectRowAt:)。所以你需要在这里实现高亮逻辑:

 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
// your logic of changing color
    

然后您应该执行类似的操作,但是要使用deselectRow(at:animated:)取消选择行,我相信这应该在用户完成操作时完成。您还需要实现类似的功能tableView(_:didDeselectRowAt:) 以返回颜色:

override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) 
// change color back

更新: 您还可以使用setHighlighted(_:animated:) 方法突出显示单元格。通过这种方式,您可以避免使用 selectRowAt/didSelectRowAt/didDeselectRowAt 和滚动 tableView 使用

tableView?.scrollToRow(at: indexPath, at: UITableViewScrollPosition.top, animated: true).

【讨论】:

以上是关于长按时像 iMessage 一样突出显示 UITableViewCell的主要内容,如果未能解决你的问题,请参考以下文章

对于 iPhone - 但不是 iOS 模拟器 - UIToolbar UIBarButtonItem 将仅在长按时突出显示,而不是在点击时突出显示

如何使用选择器在长按时“永久”突出显示 ListView 行,但在正常按下时短暂显示

如何像在 iMessage 群聊中一样在导航栏中放置集合视图

如何像在 iOS 中为 iMessage 一样为 Android 创建贴纸包?

如何像 Apple 一样突出显示 UIView

UIbutton 仅在 longPress 上看起来被点击(突出显示)?