更改UICollectionViewCell手势hitbox的形状

时间:2016-01-29 18:09:47

标签: ios swift uigesturerecognizer uicollectionviewcell

我有一堆UICollectionViewCells看起来像圆形(想象一个圆形背景图像)。我想检测何时点击其中一个,但是当前单元格的手势命中框是方形的,对应于单元格的高度和宽度。因此,点击方形形状的角落(有点在圆形外观之外)仍然会记录为手势:

circle in square

我正在考虑使用indexPathForItemAtPoint(point:)方法的方法,即我不想编写手动检查,例如for循环运行{{ 1}}。

我尝试更改单元格图层的cell.frame.containsPoint(point:),但我认为用于检测点按的相关字段是borderRadius,这是frame ...所以是它甚至可以实现我想要做的,或者我必须自己编写单元格检测代码? (类似于,获取所有单元格并计算到中心的距离,然后查看距离是否在半径范围内)

主要问题是我的布局会导致单元格框架重叠,因此当CGRect框架重叠时,indexPathForItemAtPoint(point:)当前会导致某些单元格优于其他单元格(最有可能基于visibleCells的迭代顺序)。

1 个答案:

答案 0 :(得分:1)

您可以创建UIBezierPath并检查点击是否在其中。例如,在您对UITapGestureRecognizer的操作中,您可以说类似

let location = sender.location
let indexPath = collectionView.indexPathForItemAtPoint(location)
let cell = collectionView.cellForItemAtIndexPath(indexPath!)
let newLocation = cell?.convertPoint(location, fromView: collectionView)
let circlePath = UIBezierPath(ovalInRect: (cell?.bounds)!)
if circlePath.containsPoint(newLocation!)
{
    //handle cell tap
}

或者在UICollectionViewCell的子类中,您可以添加如下内容:

override func hitTest(point: CGPoint, withEvent e: UIEvent?) -> UIView? {
        let circlePath = UIBezierPath(ovalInRect: (self.bounds))
        if circlePath.containsPoint(point)
        {
            return self
        }
        return nil
    }

这将检查点击是否位于视图的可见部分或将事件传递给较低视图。然后实现didSelectItemAtIndexPath并在那里处理tap事件。