如何防止 UITableViewCell 内的手势干扰 UITableView 的滚动?

Posted

技术标签:

【中文标题】如何防止 UITableViewCell 内的手势干扰 UITableView 的滚动?【英文标题】:How to prevent a gesture inside a UITableViewCell from interfering with the UITableView's scrolling? 【发布时间】:2018-07-31 15:47:34 【问题描述】:

我觉得这个问题之前已经被问过很多次了,但是我已经找了好几天了,找不到有效的解决方案。在 Swift 4 中,我有一个 UITableView,其中每个 UITableViewCell 里面都有可触摸的 UIView。这个 UIView 附加了一个 UILongPressGestureRecognizer ,它会影响其按下状态并在按下时导航到另一个屏幕。所有的行都相对靠近,不幸的是,为了启动平移手势来滚动 UITableView,您必须按下列表项,这会触发其手势识别器并立即离开页面。

原来,你不能按下 UITableViewCell 来触发滚动,所以我在我的 UIView 中设置了手势委托并添加了这个功能:

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool 
    return true

因此导致了我目前遇到的问题。这是我在 UITableViewCell 中使用的自定义 UIView 类:

import Foundation
import UIKit

protocol ItemViewDelegate: AnyObject 
    func tapped()


class ItemView: UIView, UIGestureRecognizerDelegate 
    weak var delegate: ItemViewDelegate?
    var parent: UIViewController?

    override init(frame: CGRect) 
        super.init(frame: frame)
        self.initializeGestureRecognition()
    

    required init?(coder aDecoder: NSCoder) 
        super.init(coder: aDecoder)
        self.initializeGestureRecognition()
    

    lazy var animator: UIViewPropertyAnimator = 
        let cubicParameters = UICubicTimingParameters(controlPoint1: CGPoint(x: 0, y: 0.5), controlPoint2: CGPoint(x: 1.0, y: 0.5))
        let animator = UIViewPropertyAnimator(duration: 0.1, timingParameters: cubicParameters)

        animator.isInterruptible = true

        return animator
    ()

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool 
        return true
    

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool 
        if (type(of: otherGestureRecognizer) == UIPanGestureRecognizer.self) 
            return true
        

        return false
    

    private func initializeGestureRecognition() 
        let tapRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(self.handleTap(from:)))

        tapRecognizer.minimumPressDuration = 0
        tapRecognizer.delegate = self
        tapRecognizer.cancelsTouchesInView = false

        self.isUserInteractionEnabled = true
        self.addGestureRecognizer(tapRecognizer)
    

    private func tapped() 
        guard let delegate = self.delegate else 
            return
        

        delegate.tapped()
    

    override func layoutSubviews() 
        super.layoutSubviews()
        self.roundCorners(radius: 4)
        self.addShadow(opacity: 0.06, radius: 4)
    

    @objc func handleTap(from recognizer: UITapGestureRecognizer) 
        switch recognizer.state 
        case .began:
            if animator.isRunning 
                animator.stopAnimation(true)
            

            animator.addAnimations 
                self.transform = CGAffineTransform(scaleX: 0.98, y: 0.98)
            

            animator.startAnimation()
        case .ended:
            if animator.isRunning 
                animator.stopAnimation(true)
            

            animator.addAnimations 
                self.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
            

            animator.startAnimation()

            self.tapped()
        default:
            break
        
    

我认为 shouldRequireFailureOf 覆盖肯定会起作用,正如 Apple 的文档所暗示的那样,但我现在已经尝试了几乎所有方法,并且正在拔头发。任何帮助,将不胜感激。谢谢!

【问题讨论】:

【参考方案1】:

你可以在包含 tableView 的 VC 中定义这个 var

var isScrolling = false

//

class ViewController: UIViewController , UIScrollViewDelegate

//

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) 

    isScrolling = true



func scrollViewDidScroll(_ scrollView: UIScrollView) 

    isScrolling = false


//

在单元格内读取这个值

@objc func handleTap(from recognizer: UITapGestureRecognizer) 

   if parentVc.isScrolling   return  

    .....

【讨论】:

这种方法似乎不起作用......不幸的是,当用户从视图中抬起手指时,isScrolling 已被设置回 false,并且无论如何都会处理点击事件。跨度>

以上是关于如何防止 UITableViewCell 内的手势干扰 UITableView 的滚动?的主要内容,如果未能解决你的问题,请参考以下文章

在 UITableViewCell 中未检测到点击手势

UITableViewCell 内的 UITextField - 防止文本重置的方法

如何向 UITableViewCell 添加手势?

如何将手势识别器添加到 UITableViewCell 的 UIImage 和 UIButton?

尝试对 UITableViewCell 应用平移手势但失败,为啥?

滑动手势取消编辑模式后 UITableViewCell 刷新不良