UITableViewAutomaticDimension 似乎没有考虑细节标签的内容。我该如何解决?

Swe*_*per 0 uitableview autolayout swift

我已经阅读了很多关于如何根据单元格中的文本自动调整表格单元格高度的内容。从这个这个这个,似乎UITableView.automaticDimension是要走的路。显然它也适用于系统(即非自定义)单元。

在我的表格视图中,我使用了一堆样式为“Right Detail”的系统单元格(请注意,这不是我的自定义单元格):

在此处输入图片说明

我让两个标签的“行”为 0,“换行”为“换行”以启用自动换行。现在在我的表 VC 中,我用一些数据填充了表视图,这些数据旨在显示我遇到的问题:

var strings = [("Some Very Long Black Text That Doesn't Fit. Foo Bar Baz.", ""),
               ("A", "Short Text"),
               ("B", "Foo Bar"),
               ("Not working:", "Some Very Long Grey Text That Doesn't Fit. Foo Bar Baz"),
               ("C", "Another Text")]

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return strings.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
    cell?.textLabel?.text = strings[indexPath.row].0
    cell?.detailTextLabel?.text = strings[indexPath.row].1
    return cell!
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableView.automaticDimension
}
Run Code Online (Sandbox Code Playgroud)

这是结果:

在此处输入图片说明

如您所见,第一行正确调整了其高度以适合标签,但第四行的标签超出了其单元格。似乎表格视图只尝试将行高调整为textLabel.text,而detailTextLabel根本不考虑文本。

在计算单元格高度时,如何让表格视图同时考虑两个标签的文本?


额外的尝试:

我想我可以创建一个与系统“Right Detail”单元格样式非常相似的自定义单元格并使用该单元格代替。无论我做什么,我都无法重新创建系统单元的约束。例如,这是我最好的尝试。

在此处输入图片说明

在此处输入图片说明

Don*_*Mag 5

让它完全按照你的意愿工作是很困难的。

自动布局进行多次“传递”以尝试满足布局要求。但是,想想它必须做什么:

  • 设置两个标签的文本
  • “leftLabel”需要换行吗?
  • “rightLabel”需要换行吗?
  • 如果“leftLabel”换行,“rightLabel”还需要换行吗?
  • 反之亦然?

并且,在该过程中的哪一点可以确定两个标签都将结束包装,因此使每个标签的宽度为 50%?请记住,单元格宽度会因设备和方向而异?

可能想要查看您希望显示的实际数据,并考虑它的实际外观。“正确的细节单元”设计最终可能不会成为最佳布局。

也就是说 - 这是一个可能适合您的自定义单元格。它需要大量的边缘测试来查看是否有任何尺寸被丢弃(例如,由于长的字符串和/或字符串长度之间的差异很大):

class MyRightDetailCell: UITableViewCell {

    var myTextLabel: UILabel = {
        let v = UILabel()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.numberOfLines = 0
        v.textAlignment = .left
        v.font = UIFont.systemFont(ofSize: 17.0)
        v.textColor = .black
        v.setContentHuggingPriority(.required, for: .horizontal)
        v.setContentHuggingPriority(.required, for: .vertical)
        v.setContentCompressionResistancePriority(.required, for: .horizontal)
        v.setContentCompressionResistancePriority(.required, for: .vertical)
        return v
    }()

    var myDetailTextLabel: UILabel = {
        let v = UILabel()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.numberOfLines = 0
        v.textAlignment = .right
        v.font = UIFont.systemFont(ofSize: 17.0)
        v.textColor = .darkGray
        v.setContentHuggingPriority(.required, for: .horizontal)
        v.setContentHuggingPriority(.required, for: .vertical)
        v.setContentCompressionResistancePriority(.required, for: .horizontal)
        v.setContentCompressionResistancePriority(.required, for: .vertical)
        return v
    }()

    var theStackView: UIStackView = {
        let v = UIStackView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.axis = .horizontal
        v.alignment = .top
        v.distribution = .fill
        v.spacing = 8
        v.setContentHuggingPriority(.required, for: .vertical)
        v.setContentCompressionResistancePriority(.required, for: .vertical)
        return v
    }()

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

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }

    func commonInit() -> Void {

        contentView.addSubview(theStackView)
        theStackView.addArrangedSubview(myTextLabel)
        theStackView.addArrangedSubview(myDetailTextLabel)

        let g = contentView.layoutMarginsGuide

        NSLayoutConstraint.activate([
            theStackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            theStackView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
            theStackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            theStackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
        ])

    }

}

class RightDetailTableViewController: UITableViewController {

    var strings = [
        ("Some Very Long Black Text That Doesn't Fit. Foo Bar Baz.", ""),
        ("A", "Short Text"),
        ("B Somewhat Much Longer Left Label Text.", "With long right label text."),
        ("Working Now?", "Some Very Long Grey Text (Three Lines?) That Doesn't Fit. Foo Bar Baz"),
        ("C", "Another Text"),
        ("D", "With Long Right Label Text That Will Need To Wrap."),
    ]

    let cellID = "MYRDC"

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(MyRightDetailCell.self, forCellReuseIdentifier: cellID)

        // make 5 copies of the test data so we'll have plenty of rows
        // for scrolling (to check cell re-use)
        for _ in 1...5 {
            strings.append(contentsOf: strings)
        }
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // due to the complexity of the cell, the layout is more reliable if the
        // table is reloaded here - try it with and without this extra reloadData() call
        tableView.reloadData()
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return strings.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) as! MyRightDetailCell

        cell.myTextLabel.text = strings[indexPath.row].0
        cell.myDetailTextLabel.text = strings[indexPath.row].1

        // if either label has no text (""), set it to hidden
        // to remove the stack view's spacing
        cell.myTextLabel.isHidden = (strings[indexPath.row].0 == "")
        cell.myDetailTextLabel.isHidden = (strings[indexPath.row].1 == "")

        // un-comment the next two lines to show label background colors
        // to make it easy to see the label frames
        //cell.myTextLabel.backgroundColor = .cyan
        //cell.myDetailTextLabel.backgroundColor = .green

        return cell
    }

}
Run Code Online (Sandbox Code Playgroud)

输出:

在此处输入图片说明