具有多个堆栈视图的自调整单元格

Self sizing cell with multiple Stack Views

我浏览了整个论坛并尝试了所有解决方案,但到目前为止没有任何效果。我注意到我的 UIImageView 覆盖了多个单元格,这意味着单元格不会自动调整其高度。这是我在它抱怨的控制台中发现的约束。

""

在我的 tableViewController 中,我有以下内容

  tableView.rowHeight = UITableView.automaticDimension
  tableView.estimatedRowHeight = 300

这是我的整个单元格,应该自动调整大小。

import UIKit

class UserConnectionCell: UITableViewCell {

fileprivate let leftImageView: UIImageView = {
    let uiImageView = UIImageView()
    uiImageView.translatesAutoresizingMaskIntoConstraints = false

   return uiImageView
}()

fileprivate let leftLabel: UILabel = {
    let label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

fileprivate let middleLabel: UILabel = {
    let label = UILabel()
    label.numberOfLines = 0
    label.font = UIFont(name: "Ariel", size: 10)
    label.textAlignment = .center
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

fileprivate let rightImageView: UIImageView = {
    let uiImageView = UIImageView()
    uiImageView.translatesAutoresizingMaskIntoConstraints = false
   return uiImageView
}()

fileprivate let rightLabel: UILabel = {
    let label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

fileprivate let stackViewLeft: UIStackView = {
    let stackView = UIStackView()
    stackView.axis = .vertical
    stackView.translatesAutoresizingMaskIntoConstraints = false
    return stackView
}()
fileprivate let stackViewRight: UIStackView = {
    let stackView = UIStackView()
    stackView.axis = .vertical
    stackView.translatesAutoresizingMaskIntoConstraints = false
    return stackView
}()
fileprivate let stackViewMain: UIStackView = {
    let stackView = UIStackView()
    stackView.axis = .horizontal
    stackView.alignment = .fill
    stackView.spacing = 0
    stackView.translatesAutoresizingMaskIntoConstraints = false
    return stackView
}()

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

    stackViewLeft.addArrangedSubview(leftImageView)
    stackViewLeft.addArrangedSubview(leftLabel)

    stackViewRight.addArrangedSubview(rightImageView)
    stackViewRight.addArrangedSubview(rightLabel)

    stackViewMain.addArrangedSubview(stackViewLeft)
    stackViewMain.addArrangedSubview(middleLabel)
    stackViewMain.addArrangedSubview(stackViewRight)

    contentView.addSubview(stackViewMain)
}
// called when trying to layout subviews.
override func layoutSubviews() {
    super.layoutSubviews()

    stackViewLeft.addConstraint(NSLayoutConstraint(item: leftImageView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: 100))
    stackViewLeft.addConstraint(NSLayoutConstraint(item: leftImageView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 100))

    stackViewRight.addConstraint(NSLayoutConstraint(item: rightImageView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1, constant: 100))
    stackViewRight.addConstraint(NSLayoutConstraint(item: rightImageView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1, constant: 100))

    NSLayoutConstraint.activate(
        [stackViewMain.topAnchor.constraint(equalTo: contentView.topAnchor,constant: 0),
         stackViewMain.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,constant: 0),
         stackViewMain.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,constant: 0),
         stackViewMain.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0)
        ])

}

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

var viewModel : UserConnectionViewModel? {
    didSet {
        // move this to the view model
        if let profileUrl = viewModel?.leftImageUrl {
            leftImageView.loadImageFromURL(url: profileUrl)
        } else {
            leftImageView.image = UIImage(named: "defaultprofile")
        }

        if let profileUrl = viewModel?.rightImageUrl {
            rightImageView.loadImageFromURL(url: profileUrl)
        } else {
            rightImageView.image = UIImage(named: "defaultprofile")
        }
        leftLabel.text = viewModel?.leftLabel
        middleLabel.text = viewModel?.middleLabel
        rightLabel.text = viewModel?.rightlabel
    }
}

override func awakeFromNib() {
    super.awakeFromNib()
    self.contentView.autoresizingMask = .flexibleHeight
    // Initialization code
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}
}

关于为什么单元格不能自动调整大小的任何想法?

首先,单元格的 contentView 是一个“特殊”视图,具有 table 视图操作不可或缺的属性。

所以,不要这样做:

self.contentView.autoresizingMask = .flexibleHeight

其次,layoutSubviews() 可以(并且通常是)在单元格/视图的生命周期中被多次调用。您的约束设置应在 init:

中完成
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier:reuseIdentifier)
    
    stackViewLeft.addArrangedSubview(leftImageView)
    stackViewLeft.addArrangedSubview(leftLabel)
    
    stackViewRight.addArrangedSubview(rightImageView)
    stackViewRight.addArrangedSubview(rightLabel)
    
    stackViewMain.addArrangedSubview(stackViewLeft)
    stackViewMain.addArrangedSubview(middleLabel)
    stackViewMain.addArrangedSubview(stackViewRight)
    
    contentView.addSubview(stackViewMain)
    
    NSLayoutConstraint.activate([
        
        // constrain main stack view to all 4 sides of contentView
        stackViewMain.topAnchor.constraint(equalTo: contentView.topAnchor,constant: 0),
        stackViewMain.leadingAnchor.constraint(equalTo: contentView.leadingAnchor,constant: 0),
        stackViewMain.trailingAnchor.constraint(equalTo: contentView.trailingAnchor,constant: 0),
        stackViewMain.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 0),

        // constrain left image view Width: 100-pts,
        //  Height equal to Width (1:1 ratio)
        leftImageView.widthAnchor.constraint(equalToConstant: 100.0),
        leftImageView.heightAnchor.constraint(equalTo: leftImageView.widthAnchor),
        
        // constrain right image view Width: 100-pts,
        //  Height equal to Width (1:1 ratio)
        rightImageView.widthAnchor.constraint(equalToConstant: 100.0),
        rightImageView.heightAnchor.constraint(equalTo: rightImageView.widthAnchor),
        
    ])
    
}

所以...用上面的代码替换你的init并且完全删除你的awakeFromNib()layoutSubviews()函数。

你应该得到这个: