在编程 collectionviewCell 中添加约束

adding constraint in programmatic collectionviewCell

我正在尝试以编程方式创建 collectionView 单元格并在代码中向子视图添加约束。我不确定我需要在代码中的什么位置添加这个。

我希望我的单元格有一个圆角视图,在其中,我有一个包含图像和标签的垂直堆栈视图。

我觉得这看起来不错,但标签超出堆栈视图的范围时出现问题。所以我需要向这个标签添加约束,但是当我这样做时,我遇到了崩溃并且 XCode 询问约束是否引用了视图子树之外的东西。

代码如下:

final class myCollectionViewCell: UICollectionViewCell {

        // MARK: - Properties

        var colorView: UIView!
        var label: UILabel!
        var img: UIImageView!

        // MARK: - Object Lifecycle

        override init(frame: CGRect) {

            super.init(frame: frame)

            self.colorView = UIView()
            colorView.layer.cornerRadius = 8

            let stackView   = UIStackView()
            stackView.axis  = UILayoutConstraintAxis.vertical
            stackView.distribution  = UIStackViewDistribution.fill
            stackView.alignment = UIStackViewAlignment.center
            stackView.spacing   = 16.0
            stackView.center = self.contentView.center

            self.label = UILabel()
            label.numberOfLines = 0
            label.lineBreakMode = .byWordWrapping
            label.widthAnchor.constraint(equalToConstant: self.contentView.frame.width).isActive = true
            label.textAlignment = .center

            self.img = UIImageView()
            img.heightAnchor.constraint(equalToConstant: 100.0).isActive = true
            img.widthAnchor.constraint(equalToConstant: 100.0).isActive = true

            stackView.addArrangedSubview(img)
            stackView.addArrangedSubview(label)
            stackView.translatesAutoresizingMaskIntoConstraints = false


            label.addConstraint(NSLayoutConstraint(item: stackView, attribute: .trailing, relatedBy: .equal, toItem: label, attribute: .trailing, multiplier: 1, constant: 20))
            label.addConstraint(NSLayoutConstraint(item: stackView, attribute: .leading, relatedBy: .equal, toItem: label, attribute: .leading, multiplier: 1, constant: 20))

            self.colorView.addSubview(stackView)

            self.contentView.addSubview(self.colorView)
        }

        required init?(coder aDecoder: NSCoder) {

            fatalError("init(coder:) has not been implemented")
        }

        // MARK: - Layout

        override func layoutSubviews() {

            super.layoutSubviews()

            self.label.sizeToFit()

            self.img.layer.cornerRadius = self.img.frame.width/2
            self.img.clipsToBounds = true
            self.colorView.frame = CGRect(origin: CGPoint.zero, size: self.contentView.bounds.size)
        }

        override class var requiresConstraintBasedLayout: Bool {

            return false
        }
    }

此外,我的图像视图只会在滚动时变圆。我应该把 cornerRadiusclipsToBounds 属性 放在哪里?

这里有一些关于 collectionView 布局的额外信息:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: 10.0, left: 10.0, bottom: 10.0, right: 10.0)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {

        return 10.0
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {

        return 10.0
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let itemWidth : CGFloat = 100
        let itemHeight : CGFloat = 250.0
        return CGSize(width: itemWidth, height: itemHeight)
    }

要创建带圆角的 imageView,您可以使用这样的闭包:

var imageView: UIImageView = {
   let imageView = UIImageView()
   imageView.layer.cornerRadius = 5.0 //Or whatever you want
   imageView.clipsToBounds = true
   return imageView 
 }()

已编辑

首先,将子视图添加到堆栈视图时,不需要对其设置约束。只需为堆栈视图本身设置约束并更改其参数(如 spacing)。这是图像视图及其下方标签的实现:

 let imageView: UIImageView = {
    let imgView = UIImageView()
    imgView.backgroundColor = .red
    imgView.layer.cornerRadius = 4.0
    imgView.clipsToBounds = true
    return imgView
}()

let label: UILabel = {
   let label = UILabel()
    label.text = "SOME DUMMY TEXT"
    label.font = UIFont.systemFont(ofSize: 16)
    label.numberOfLines = 0
    label.minimumScaleFactor = 0.9

    return label
}()

lazy var verticalStackView: UIStackView = {
   let stackView = UIStackView(arrangedSubviews: [self.imageView, self.label])
    stackView.axis = .vertical
    stackView.distribution = .fill
    stackView.spacing = 2.0
    return stackView
}()


override init(frame: CGRect) {
    super.init(frame: frame)
    handleConstraints()
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}


func handleConstraints() {

    verticalStackView.translatesAutoresizingMaskIntoConstraints = false
    self.addSubview(verticalStackView)

    verticalStackView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
    verticalStackView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
    verticalStackView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
    verticalStackView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
}

我使用不同的语法来创建约束,因为我认为这个更清晰。您可以轻松地将其转换为您喜欢的语法。

这可能是因为您已将 requiresConstraintBasedLayout 设置为 false,这会在您仍在尝试使用约束时自动停用布局系统。