添加到自定义 UICollectionViewCell 时出现意外的 CAShapeLayer 行为

Posted

技术标签:

【中文标题】添加到自定义 UICollectionViewCell 时出现意外的 CAShapeLayer 行为【英文标题】:Unexpected CAShapeLayer behavior when added to custom UICollectionViewCell 【发布时间】:2021-01-31 06:00:50 【问题描述】:

我一直试图弄清楚这一点,但我已经用尽了我的搜索。我一直在尝试将 CAShapeLayer 添加到自定义 UICollectionViewCell,但它要么不被绘制,要么有时只被绘制。我决定使用以下代码简化我遇到的问题:

class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout 
    
    let cellId = "cell"
    let dataSource: [UIColor] = [.blue, .purple, .brown, .green, .red]

    override func viewDidLoad() 
        super.viewDidLoad()
        collectionView.isPagingEnabled = true
        collectionView.register(CellSubclass.self, forCellWithReuseIdentifier: cellId)
    
    
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return dataSource.count
    
    
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! CellSubclass
        cell.backgroundColor = dataSource[indexPath.item]
        return cell
    
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
        return CGSize(width: view.frame.width, height: view.frame.height)
    


class CellSubclass: UICollectionViewCell 
    
    let circle = CAShapeLayer()
    
    override init(frame: CGRect) 
        super.init(frame: frame)
        circle.frame = bounds

        let circleCenter = self.center
        let path = UIBezierPath(arcCenter: circleCenter, radius: 100, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
        circle.path = path.cgPath
        circle.fillColor = UIColor.gray.cgColor
        layer.addSublayer(circle)
    
    
    required init?(coder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    

我有以下 UICollectionViewController 的流布局

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = 0
let home = ViewController(collectionViewLayout: layout)

基于我见过的其他 *** 问题,人们建议在自定义 UICollectionViewCell 初始化时采用将形状子层添加到自定义 UICollectionViewCell 的方法,就像我已经完成的那样。但是,当我运行此代码时,我得到以下输出:

任何有关如何解决此行为的帮助,以便自定义单元格的每个实例都有自己的形状,我们将不胜感激。

【问题讨论】:

【参考方案1】:

改变

    let circleCenter = self.center

    let circleCenter = CGPoint(x:self.bounds.midX, y:self.bounds.midY)

【讨论】:

【参考方案2】:

init() 期间,您的单元格类不知道其大小。

layoutSubviews()中设置层路径,你会有更好的运气:

class CellSubclass: UICollectionViewCell 
    
    let circle = CAShapeLayer()
    
    override init(frame: CGRect) 
        super.init(frame: frame)
        
        circle.fillColor = UIColor.gray.cgColor
        layer.addSublayer(circle)
    
    
    required init?(coder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    
    
    override func layoutSubviews() 
        super.layoutSubviews()

        circle.frame = bounds
        let circleCenter = CGPoint(x: bounds.midX, y: bounds.midY)
        let path = UIBezierPath(arcCenter: circleCenter, radius: 100, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
        circle.path = path.cgPath
    

注意:如果/当单元格大小发生变化时(例如设备旋转),这也会使圆保持居中。

【讨论】:

以上是关于添加到自定义 UICollectionViewCell 时出现意外的 CAShapeLayer 行为的主要内容,如果未能解决你的问题,请参考以下文章

将 UIImageView 添加到自定义 UITableViewCell

将滚动条添加到自定义 QWidget

将子视图添加到自定义类

以编程方式将 UILabel 添加到自定义 tableViewCell

将多个自定义栏按钮添加到自定义导航栏

如何将暗色背景添加到自定义 UIPopoverBackgroundView