UITableViewAutomaticDimension 未按预期工作。 Swift
UITableViewAutomaticDimension works not as expected. Swift
阅读 Ray Wenderlich guide for "Self-sizing Table View Cells" as well as 和答案后,我决定向大家寻求帮助。
有一个编程创建的单元格:
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()
}
}
table 视图控制器在委托方法中使用 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
中进行设置:
self.tableView.rowHeight = UITableViewAutomaticDimension;
// set estimatedRowHeight to whatever is the fallBack rowHeight
self.tableView.estimatedRowHeight = 44.0;
这对我来说总是有效的。让我知道是否有帮助:)
更新以下行:
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;
以下步骤可能会解决您的问题:
1) 为单元格中的 UILabel 设置顶部、底部、前导和尾随约束,如下所示:
2) 配置表视图:
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 44.0;
你做错了很多事情,但 主要 点是你对 greaterThanOrEqualTo:
的使用。
相反,它应该是:
cellCaption.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8),
此外,您当前的代码是在每次设置文本时添加一个新标签作为子视图。单元格被重复使用,因此您只想在创建单元格时添加标签。
接下来,table 的正确属性是:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44
将这两行放在 table 视图控制器的 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
}
}
结果:
在Swift 5:
func configureTableView() {
myTableView.rowHeight = UITableView.automaticDimension
myTableView.estimatedRowHeight = 44
}
请记住,如果 .estimatedRowHeight
不正确,Swift 会为您计算。最后在viewDidLoad()
中调用这个方法
阅读 Ray Wenderlich guide for "Self-sizing Table View Cells" as well as
有一个编程创建的单元格:
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()
}
}
table 视图控制器在委托方法中使用 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
中进行设置:
self.tableView.rowHeight = UITableViewAutomaticDimension;
// set estimatedRowHeight to whatever is the fallBack rowHeight
self.tableView.estimatedRowHeight = 44.0;
这对我来说总是有效的。让我知道是否有帮助:)
更新以下行:
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;
以下步骤可能会解决您的问题:
1) 为单元格中的 UILabel 设置顶部、底部、前导和尾随约束,如下所示:
2) 配置表视图:
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 44.0;
你做错了很多事情,但 主要 点是你对 greaterThanOrEqualTo:
的使用。
相反,它应该是:
cellCaption.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -8),
此外,您当前的代码是在每次设置文本时添加一个新标签作为子视图。单元格被重复使用,因此您只想在创建单元格时添加标签。
接下来,table 的正确属性是:
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 44
将这两行放在 table 视图控制器的 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
}
}
结果:
在Swift 5:
func configureTableView() {
myTableView.rowHeight = UITableView.automaticDimension
myTableView.estimatedRowHeight = 44
}
请记住,如果 .estimatedRowHeight
不正确,Swift 会为您计算。最后在viewDidLoad()