以编程方式对单元格内容进行约束

Cell content constraints programmatically

提问人:CalebGates 提问时间:7/8/2023 更新时间:7/8/2023 访问量:37

问:

我正在尝试以编程方式重做我的项目,没有故事板。我有一个带有原型单元格的 tableView。

该单元格包含 imageView(公文包)、firstLabel(位于顶部)和 secondLabel(位于 firstLabel 的正下方)。我尝试设置约束,但由于某种原因,secondLabel根本没有显示,并且单元格高度不会自动调整到内容高度。

下面是单元格的代码:

import UIKit

class Cell: UITableViewCell {

    let briefcaseImage: UIImageView = {
        let img = UIImageView(image: UIImage(systemName: "briefcase"))
        img.contentMode = .scaleAspectFill
        img.tintColor = UIColor(red: 0.20, green: 0.68, blue: 0.90, alpha: 1.00)
        img.translatesAutoresizingMaskIntoConstraints = false
        img.clipsToBounds = true
        return img }()

    let firstLabel: UILabel = {
        let label = UILabel()
        label.numberOfLines = 0
        label.lineBreakMode = .byWordWrapping
        label.font = UIFont.systemFont(ofSize: 17)
        label.translatesAutoresizingMaskIntoConstraints = false
        return label }()

    let secondLabel: UILabel = {
        let label = UILabel()
        label.numberOfLines = 0
        label.lineBreakMode = .byWordWrapping
        label.textAlignment = .right
        label.font = UIFont.systemFont(ofSize: 15)
        label.translatesAutoresizingMaskIntoConstraints = false
        return label }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.contentView.addSubview(briefcaseImage)
        self.contentView.addSubview(firstLabel)
        self.contentView.addSubview(secondLabel)
    
        //MARK: Constraints for the briefcaseImage
        briefcaseImage.topAnchor.constraint(equalTo: topAnchor, constant: 11).isActive = true
        briefcaseImage.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16).isActive = true
        briefcaseImage.heightAnchor.constraint(equalToConstant: 22.5).isActive = true
        briefcaseImage.widthAnchor.constraint(equalToConstant: 20.0).isActive = true
    
        //MARK: Constraints for the firstLabel
        firstLabel.topAnchor.constraint(equalTo: topAnchor, constant: 11).isActive = true
        firstLabel.leadingAnchor.constraint(equalTo: briefcaseImage.trailingAnchor, constant: 10).isActive = true
        firstLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16).isActive = true
    
        //MARK: Constraints for the secondLabel
        secondLabel.topAnchor.constraint(equalTo: firstLabel.bottomAnchor, constant: 4.5).isActive = true
        secondLabel.leadingAnchor.constraint(equalTo: briefcaseImage.trailingAnchor, constant: 10).isActive = true
        secondLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16).isActive = true
        secondLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -11).isActive = true
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

此外,当我运行应用程序时,我在调试器部分收到此错误:

Detected a case where constraints ambiguously suggest a height of zero for a table view cell's content view. We're considering the collapse unintentional and using standard height instead.

这是单元格的样子(不是我想要的):

enter image description here

如何正确修复约束,以便显示 secondLabel,并且单元格高度自动调整为内容高度?

iOS Swift UITableView 自动布局 约束

评论


答:

0赞 Fabio 7/8/2023 #1

为此,您必须在 Cell 中使用 stackView,首先将 heightForRowAt 返回给 UITableView.automaticDimension(在这种情况下,您还会删除 heightForRowAt,因为它是默认设置):

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}

之后,在单元格中将 stackView 和约束设置为 contentView,而不是直接设置为单元格,如下所示:

class Cell: UITableViewCell {

let briefcaseImage: UIImageView = {
    let img = UIImageView(image: UIImage(systemName: "briefcase"))
    img.contentMode = .scaleAspectFill
    img.tintColor = UIColor(red: 0.20, green: 0.68, blue: 0.90, alpha: 1.00)
    img.translatesAutoresizingMaskIntoConstraints = false
    img.clipsToBounds = true
    return img }()

let firstLabel: UILabel = {
    let label = UILabel()
    label.numberOfLines = 0
    label.lineBreakMode = .byWordWrapping
    label.font = UIFont.systemFont(ofSize: 17)
    label.textColor = .black
    label.translatesAutoresizingMaskIntoConstraints = false
    return label }()

let secondLabel: UILabel = {
    let label = UILabel()
    label.numberOfLines = 0
    label.lineBreakMode = .byWordWrapping
    label.textAlignment = .right
    label.font = UIFont.systemFont(ofSize: 15)
    label.textColor = .black
    label.translatesAutoresizingMaskIntoConstraints = false
    return label }()

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    contentView.addSubview(briefcaseImage)
    contentView.backgroundColor = .white

    //MARK: Constraints for the briefcaseImage
    briefcaseImage.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 11).isActive = true
    briefcaseImage.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16).isActive = true
    briefcaseImage.heightAnchor.constraint(equalToConstant: 22.5).isActive = true
    briefcaseImage.widthAnchor.constraint(equalToConstant: 20.0).isActive = true
    
    let stackView = UIStackView(arrangedSubviews: [firstLabel, secondLabel])
    stackView.axis = .vertical
    stackView.spacing = 2
    stackView.distribution = .fill
    stackView.translatesAutoresizingMaskIntoConstraints = false
    
    contentView.addSubview(stackView)
    stackView.topAnchor.constraint(equalTo: briefcaseImage.topAnchor).isActive = true
    stackView.leadingAnchor.constraint(equalTo: briefcaseImage.trailingAnchor, constant: 10).isActive = true
    stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16).isActive = true
    stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -11).isActive = true
}

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

结果如下:

enter image description here

评论

0赞 CalebGates 7/8/2023
啊,好老法比奥,总是有有用的答案!非常感谢,当我到达我的机器时会检查一下。顺便说一句,你是如何让你的导航项目变成白色的?无论如何我都做不到