如何将 UICollectionViewCell 的可触摸区域扩展到其边界之外?

Posted

技术标签:

【中文标题】如何将 UICollectionViewCell 的可触摸区域扩展到其边界之外?【英文标题】:How can I expand the touchable area of a UICollectionViewCell beyond its bounds? 【发布时间】:2015-04-04 21:27:20 【问题描述】:

我有一个集合视图单元格,其标签延伸到单元格边界之外。单元格不会剪切标签。如果用户点击超出单元格边界的标签部分,我希望 didSelectItemAtIndexPath 检测选择。我该怎么做?

【问题讨论】:

【参考方案1】:

子视图的可触摸性通常不会超出父视图的范围。因此,您需要为您的集合视图单元格类进行命中测试,以便即使触摸超出单元格边界,它的子视图也是可触摸的。

在我的书中,我给出了一个example(您可以下载并在您的机器上试用),其工作原理如下:

override func hitTest(_ point: CGPoint, with e: UIEvent?) -> UIView? 
    if let result = super.hitTest(point, with:e) 
        return result
    
    for sub in self.subviews.reversed() 
        let pt = self.convert(point, to:sub)
        if let result = sub.hitTest(pt, with:e) 
            return result
        
    
    return nil

不过,您可能需要稍微调整一下,因为标签可能不是单元格的直接子视图(如该示例代码中所假设的那样)。但是,它确实显示了这个想法。

【讨论】:

这里所涉及的理论和实践,请看我的前一版:apeth.com/iosBook/ch18.html#_hit_testing【参考方案2】:

实现此目的的一种方法是继承 UICollectionViewCell 并覆盖 pointInside(_:withEvent:) 以返回 true 如果该点位于单元格的标签内:

override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool 
    let pointInLabelCoords = convertPoint(point, toView: label)
    if label.pointInside(pointInLabelCoords, withEvent: event) 
        return true
    
    return super.pointInside(point, withEvent: event)

或者,如果您需要一个更强大的解决方案,允许触摸任何越界子视图,只需枚举 contentView.subviews 并询问每个视图点是否在内部。

请记住,这种方法只有在单元格(包括其可触摸的越界子视图)完全包含在单元格的父视图中时才有效。这是因为当系统查找视图以响应触摸时遍历视图层次结构的方式(请参阅hitTest(_:withEvent:))。如果可触摸区域位于单元格的超级视图边界之外,您还需要在 那个 视图(集合视图)上覆盖 pointInside(_:withEvent:)

【讨论】:

以上是关于如何将 UICollectionViewCell 的可触摸区域扩展到其边界之外?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 UICollectionViewCell 高度设置为视图(屏幕)高度的 90%?

如何将导航栏移到 UICollectionViewCell 之外?

如何将 UIView 约束为 UICollectionViewCell

如何将 UICollectionViewCell 放在前面?

如何将 UICollectionViewCell 嵌套在另一个中?

如何将 UITapGestureRecognizer 添加到 UICollectionViewCell 中的图像