在编程 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
}
}
此外,我的图像视图只会在滚动时变圆。我应该把 cornerRadius
和 clipsToBounds
属性 放在哪里?
这里有一些关于 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,这会在您仍在尝试使用约束时自动停用布局系统。
我正在尝试以编程方式创建 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
}
}
此外,我的图像视图只会在滚动时变圆。我应该把 cornerRadius
和 clipsToBounds
属性 放在哪里?
这里有一些关于 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,这会在您仍在尝试使用约束时自动停用布局系统。