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

时间:2018-07-05 19:42:05

标签: swift uicollectionviewcell calayer shadow cashapelayer

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

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”内部?

1 个答案:

答案 0 :(得分:2)

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

您应该创建UITableViewCell的子类,然后创建CAShapeLayer的实例并将其指针存储在类属性变量中。一旦发生布局周期,就需要在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()
    }
}

我希望这会有所帮助。