设备方向更改后使 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()
}
}
希望对您有所帮助。
我有一个自定义集合视图单元格,它使用以下代码向单元格层添加虚线边框:
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()
}
}
希望对您有所帮助。