设备方向更改后使 collectionViewCell 中的 CAShapeLayer 无效并重绘

Invalidate and Redraw CAShapeLayer inside collectionViewCell after device orientation change

我有一个自定义集合视图单元格,它使用以下代码向单元格层添加虚线边框:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = appDealCollectionView.dequeueReusableCell(withReuseIdentifier: "appDealCollectionCell", for: indexPath) as! AppDealCollectionViewCell
    if let codes = discountCodes {
        cell.discountCodeTitle.text = codes[indexPath.row].codeMessageOne
        cell.discountCode.text = codes[indexPath.row].code

        let yourViewBorder = CAShapeLayer()
        yourViewBorder.strokeColor = UIColor.black.cgColor
        yourViewBorder.lineWidth = 2
        yourViewBorder.lineDashPattern = [10, 10]
        yourViewBorder.frame = cell.bounds
        yourViewBorder.fillColor = nil
        yourViewBorder.path = UIBezierPath(roundedRect: cell.bounds, cornerRadius: 6).cgPath
        cell.layer.addSublayer(yourViewBorder)
    }
    return cell
}

此代码在初始加载视图时运行良好。但是,当方向改变时,单元格大小也会改变。上面的代码确实正确地绘制了新的边框 CAShapeLayer,但是之前绘制的边框图层仍然存在,它是根据旧尺寸绘制的。

结果是两个不同的边界层同时出现,彼此重叠,尺寸不同。

如何使之前绘制的 CAShapeLayers 失效?无效在哪里完成?在 cellForItemAt 中?或者可能在自定义 "AppDealCollectionViewCell" 本身内部?

由于单元格是可重复使用的,因此每次调用 cellForRowAtIndexPath 都会将 CAShapeLayer 的另一个实例添加到单元格中。这就是为什么您有几个边界相互重叠的原因。另外 CALayer 既不支持自动布局也不支持 autoresizingMask,因此您必须手动更新 CAShapeLayer 的大小。

您应该创建 UITableViewCell 的子 class,然后创建 CAShapeLayer 的实例并将指向它的指针存储在 class 属性 变量中。一旦发生布局循环,在 layoutSubviews 函数中,您需要更新 CAShapeLayer.

的框架

最终实现如下所示:

class BorderedTableViewCell: UITableViewCell {

    lazy var borderLayer = CAShapeLayer()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupBorderLayer()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupBorderLayer()
    }

    private func setupBorderLayer() {
        borderLayer.strokeColor = UIColor.black.cgColor
        borderLayer.lineWidth = 2
        borderLayer.fillColor = nil
        borderLayer.lineDashPattern = [10, 10]
        layer.addSublayer(borderLayer)
    }

    private func updateBorderLayer() {
        borderLayer.frame = bounds
        borderLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: 6).cgPath
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        updateBorderLayer()
    }
}

希望对您有所帮助。