UITableViewAutomaticDimension 不像预期的那样工作。迅速
Posted
技术标签:
【中文标题】UITableViewAutomaticDimension 不像预期的那样工作。迅速【英文标题】:UITableViewAutomaticDimension works not as expected. Swift 【发布时间】: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
我认为附上的截图来自模拟器,请在真机上查看。
很遗憾,在真机上结果也是一样的
【参考方案1】:
我建议不要根据您的需要使用委托方法。
试着在你的viewDidLoad
中设置这个:
self.tableView.rowHeight = UITableViewAutomaticDimension;
// set estimatedRowHeight to whatever is the fallBack rowHeight
self.tableView.estimatedRowHeight = 44.0;
这总是对我有用。让我知道是否有帮助:)
【讨论】:
@YuriIvashin 如果这不起作用,您应该更深入地了解您的约束。毫无疑问,单元格需要能够计算单元格的高度。 约束尽可能简单。试图更改顶部和底部约束的优先级。结果是一样的 @YuriIvashin 你看过这里吗? ***.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()
中,不要实现heightForRowAt
或estimatedHeightForRowAt
函数。您可以完全删除您的extension
。
最后,您只需要设置一次约束。绝对 NOT 在layoutSubviews()
。
这是一个完整的例子:
//
// 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()
中调用这个方法
【讨论】:
以上是关于UITableViewAutomaticDimension 不像预期的那样工作。迅速的主要内容,如果未能解决你的问题,请参考以下文章