如何在单击UICollectionViewCell时在其周围绘制一个圆并从以前选择的单元格中删除其他圆?

时间:2018-10-10 13:34:39

标签: ios swift uicollectionviewcell

我最近一直在使用UICollectionView。有一个需要实现的要求,例如:“几个collectionview单元中有多个imageview。当用户选择一个图像/单元时,该应用将在该图像/单元周围绘制一个蓝色圆圈。” 目前,我可以在单元上进行抽奖了。但是现在的问题是我一次只能绘制所有单元格,而不能绘制一个单元格(如下图所示)

enter image description here

所以我的问题是:如何选择一个图像/单元格,应该删除上一个选定单元格的蓝色圆圈?

非常感谢您预先提供答案。

1 个答案:

答案 0 :(得分:0)

听起来像您想要这样:

demo

您没有说出如何将蓝色圆圈放入单元格中。我认为这是您应该进行选择的方式:尽可能使用集合视图的内置选择支持。

UICollectionView已支持选择单元格。默认情况下,其allowsSelection属性为true,而其allowsMultipleSelection属性为false,因此它允许用户通过点击项目一次选择一个项目。听起来几乎就是您想要的。

集合视图在其indexPathsForSelectedItems属性中提供当前选择,当未选择任何单元格时该属性为nil或为空,并且在选择一项时仅包含一个索引路径。

当一个项目被选中,并且该项目有一个可见的单元格时,该单元格通过使其selectedBackgroundView可见来显示该项目已被选中。因此,创建一个显示蓝色圆圈的UIView子类:

class CircleView: UIView {

    override class var layerClass: AnyClass { return CAShapeLayer.self }

    override func layoutSubviews() {
        super.layoutSubviews()

        let layer = self.layer as! CAShapeLayer
        layer.strokeColor = UIColor.blue.cgColor
        layer.fillColor = nil
        let width: CGFloat = 3
        layer.lineWidth = width
        layer.path = CGPath(ellipseIn: bounds.insetBy(dx: width / 2, dy: width / 2), transform: nil)
    }
}

然后使用CircleView的实例作为单元格的selectedBackgroundView。您可以在第一次选择该单元格时延迟创建实例:

class MyCell: UICollectionViewCell {
    override var isSelected: Bool {
        willSet {
            if newValue && selectedBackgroundView == nil {
                selectedBackgroundView = CircleView()
            }
        }
    }

    var title: String = "???" {
        didSet {
            label.text = title
        }
    }

    @IBOutlet private var label: UILabel!
}

使用此代码后,用户可以点击一个单元格以选择其项目,并且选中该单元格时将显示一个蓝色圆圈。轻按另一个单元格将取消选择先前选择的项目,蓝色圆圈将“移动”到新选择的项目的单元格。

您可能想让用户通过再次点按来取消选择所选项目。如果UICollectionView为假,默认情况下allowsMultipleSelection不会这样做。启用重新点击选择的一种方法是在collectionView(_:shouldSelectItemAt:)中实现UICollectionViewDelegate

    override func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
        if (collectionView.indexPathsForSelectedItems ?? []).contains(indexPath) {
            // Item is already selected, so deselect it.
            collectionView.deselectItem(at: indexPath, animated: false)
            return false
        } else {
            return true
        }
    }