【问题标题】:UITableViewAutomaticDimension works not as expected. SwiftUITableViewAutomaticDimension 不像预期的那样工作。迅速
【发布时间】:2018-08-29 08:40:37
【问题描述】:

在阅读 Ray Wenderlich guide 的“Self-sizing Table View Cells”以及 this question 并回答之后,我决定向大家寻求帮助。

有一个以编程方式创建的单元格:

import UIKit

class NotesCell: UITableViewCell {
lazy private var cellCaption: UILabel = {
    let label = UILabel()

    label.translatesAutoresizingMaskIntoConstraints = false
    label.font = UIFont.systemFont(ofSize: 20, weight: UIFont.Weight.medium)
    label.numberOfLines = 0
    label.lineBreakMode = .byWordWrapping

    return label
}()

func configure(with note: NotesModel) {
    cellCaption.text = note.name

    contentView.addSubview(cellCaption)
}

override func layoutSubviews() {
    super.layoutSubviews()

    NSLayoutConstraint.activate([
        cellCaption.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
        cellCaption.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8),
        cellCaption.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8),
//            cellCaption.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8),
cellCaption.bottomAnchor.constraint(greaterThanOrEqualTo: contentView.bottomAnchor, constant: -8)
            ])

//        cellCaption.sizeToFit()
//        cellCaption.layoutIfNeeded()
}
}

表格视图控制器在委托方法中使用 UITableViewAutomaticDimension:

extension NotesTableViewController {
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

}

因此,最长的标题被完全指示,但单元格的高度与所有其他单元格的高度相同。

一些更新!

我已经尝试将以下代码放入 viewDidLoad() 中:

tableView.rowHeight = 44
tableView.estimatedRowHeight = UITableViewAutomaticDimension

启用委托方法并同时禁用它们。结果是一样的:(

【问题讨论】:

  • 在 viewDidLoad() 中试试这个:tableView.estimatedRowHeight = 50
  • 我认为附上的截图来自模拟器,请在真机上查看。
  • 很遗憾,在真机上结果也是一样的

标签: ios swift uitableview uitableviewautomaticdimension


【解决方案1】:

我建议不要根据您的需要使用委托方法。

试着在你的viewDidLoad中设置这个:

self.tableView.rowHeight = UITableViewAutomaticDimension;
// set estimatedRowHeight to whatever is the fallBack rowHeight
self.tableView.estimatedRowHeight = 44.0;

这总是对我有用。让我知道是否有帮助:)

【讨论】:

  • @YuriIvashin 如果这不起作用,您应该更深入地了解您的约束。毫无疑问,单元格需要能够计算单元格的高度。
  • 约束尽可能简单。试图更改顶部和底部约束的优先级。结果是一样的
  • @YuriIvashin 你看过这里吗? stackoverflow.com/questions/27288507/…
  • 已放入 tableViewController: override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() tableView.layoutSubviews() } 以及在单元格的 layoutSubviews 中调用 self.layoutIfNeeded()。结果是一样的
  • 如果您希望我在您的问题中进一步展示它。听起来你把它放在 TableViewController 但我猜你应该把它放在你的 TableViewCell 中。
【解决方案2】:

你做错了很多事情,但主要点是你使用了greaterThanOrEqualTo:

相反,它应该是:

cellCaption.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8),

此外,您当前的代码每次设置文本时都会添加一个新标签作为子视图。单元格被重复使用,因此您只想在创建单元格时添加标签。

接下来,表格的正确属性是:

    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 44

将这两行放在表格视图控制器的viewDidLoad() 中,不要实现heightForRowAtestimatedHeightForRowAt 函数。您可以完全删除您的extension

最后,您只需要设置一次约束。绝对 NOTlayoutSubviews()

这是一个完整的例子:

//
//  NotesTableViewController.swift
//
//  Created by Don Mag on 8/29/18.
//

import UIKit

class NotesModel: NSObject {
    var name: String = ""
}

class NotesCell: UITableViewCell {
    lazy private var cellCaption: UILabel = {
        let label = UILabel()

        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = UIFont.systemFont(ofSize: 20, weight: UIFont.Weight.medium)
        label.numberOfLines = 0
        label.lineBreakMode = .byWordWrapping

        return label
    }()

    func configure(with note: NotesModel) {
        cellCaption.text = note.name
    }

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

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

    func commonInit() -> Void {

        contentView.addSubview(cellCaption)

        NSLayoutConstraint.activate([
            cellCaption.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
            cellCaption.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8),
            cellCaption.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8),
            cellCaption.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8),
            ])

    }

}

class NotesTableViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 44
    }

    // MARK: - Table view data source

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

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

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

        let m = NotesModel()

        if indexPath.row == 3 {
            m.name = "This is a very long caption. It will demonstrate how the cell height is auto-sized when the text is long enough to wrap to multiple lines."
        } else {
            m.name = "Caption \(indexPath.row)"
        }

        cell.configure(with: m)

        return cell
    }

}

结果:

【讨论】:

  • 非常感谢!
  • 据我了解,我错的主要原因是使用 layoutSubviews()?
  • 不.. 真的没有 main 错误...你有错误的约束,你添加错误的子视图,你有 .rowHeight.estimatedRowHeight 错误. (对不起,不是说错了,错了,错了……)
  • 没问题!所以......只是有很多错误导致了这样一个意想不到的结果。
【解决方案3】:

更新以下行:

cellCaption.bottomAnchor.constraint(greaterThanOrEqualTo: contentView.bottomAnchor, constant: -8)
            ])

到:

cellCaption.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8)
            ])

并在 viewDidLoad 中添加以下内容:

self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 44.0;

【讨论】:

    【解决方案4】:

    以下步骤可能会解决您的问题:

    1) 为单元格中的 UILabel 设置顶部、底部、前导和尾部约束,如下所示:

    2) 配置tableview:

    self.tableView.rowHeight = UITableViewAutomaticDimension;
    self.tableView.estimatedRowHeight = 44.0;
    

    【讨论】:

    • 以编程方式创建单元格
    • @YuriIvashin 您是否还以编程方式将所有约束添加到单元格的标签?
    【解决方案5】:

    在 Swift 5 中:

    func configureTableView() {
            myTableView.rowHeight =  UITableView.automaticDimension
            myTableView.estimatedRowHeight = 44
        }
    

    请记住,如果 .estimatedRowHeight 不正确,Swift 会为您计算。最后在viewDidLoad()中调用这个方法

    【讨论】:

      猜你喜欢
      • 2014-05-16
      • 1970-01-01
      • 2012-06-13
      • 2018-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-16
      • 2016-03-07
      相关资源
      最近更新 更多