如何为具有动态高度的表格单元格正确设置自动布局?
Posted
技术标签:
【中文标题】如何为具有动态高度的表格单元格正确设置自动布局?【英文标题】:How to set auto layout correctly for a table cell with dynamic height? 【发布时间】:2017-12-22 07:31:02 【问题描述】:我尝试创建一个UITableViewCell
并设置子视图如下:
class MyCellView: UITableViewCell
private let ImageView = UIImageView()
private let titleView = UILabel()
override init(style: UITableViewCellStyle, reuseIdentifier: String?)
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(ImageView)
contentView.addSubview(titleView)
ImageView.translatesAutoresizingMaskIntoConstraints = false
ImageView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
ImageView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
ImageView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
ImageView.heightAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.6).isActive = true
titleView.translatesAutoresizingMaskIntoConstraints = false
titleView.topAnchor.constraint(equalTo: ImageView.bottomAnchor).isActive = true
titleView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
titleView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
titleView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
titleView.numberOfLines = 0
titleView.text = " " // <-- *** please note this line
在表格视图中,我已将其设置为使用动态高度:
tableView.estimatedRowHeight = 80
tableView.rowHeight = UITableViewAutomaticDimension
我的问题是,如果我没有在单元格中设置titleView
的文本,例如我在单元格视图中备注最后一行:
// titleView.text = " "
我会从 XCode 中得到约束错误。但如果我设置文本,一切正常。
文本是从 Internet 动态下载的,因此文本可能为空。另外我可以把文本设置为“”,一个空格,我想知道我在这里有什么误解吗?如果我更正某些内容,文本可以为空(“”或 nil)吗?
同样,如果我完全删除有关titleView
的代码,我只想在单元格中有一个UIImageView
,我发现单元格的高度没有扩大。如何设置它以便我可以在单元格中获得动态高度的图像?
编辑:约束错误:
2017-12-22 15:35:34.715865+0800 MyProject[15774:733515] [LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x60c000095450 V:|-(0)-[UIImageView:0x7ff40df0de90] (active, names: '|':UITableViewCellContentView:0x7ff40df0edc0 )>",
"<NSLayoutConstraint:0x60c0000955e0 UIImageView:0x7ff40df0de90.height == 0.6*UITableViewCellContentView:0x7ff40df0edc0.width (active)>",
"<NSLayoutConstraint:0x60c000095630 V:[UIImageView:0x7ff40df0de90]-(0)-[UILabel:0x7ff40df0e0c0] (active)>",
"<NSLayoutConstraint:0x60c0000957c0 UILabel:0x7ff40df0e0c0.bottom == UITableViewCellContentView:0x7ff40df0edc0.bottom (active)>",
"<NSLayoutConstraint:0x60c000096210 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7ff40df0edc0.height == 248.333 (active)>",
"<NSLayoutConstraint:0x60c000095ea0 'UIView-Encapsulated-Layout-Width' UITableViewCellContentView:0x7ff40df0edc0.width == 414 (active)>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x60c000095630 V:[UIImageView:0x7ff40df0de90]-(0)-[UILabel:0x7ff40df0e0c0] (active)>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
【问题讨论】:
什么是约束错误? @MilanNosáľ 已更新。 【参考方案1】:如果你想避免警告,试试下面的代码
class MyCellView: UITableViewCell
private let ImageView = UIImageView()
private let titleView = UILabel()
override init(style: UITableViewCellStyle, reuseIdentifier: String?)
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(ImageView)
contentView.addSubview(titleView)
ImageView.translatesAutoresizingMaskIntoConstraints = false
ImageView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
ImageView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
ImageView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
let heightConstraint = ImageView.heightAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.6)
heightConstraint.priority = UILayoutPriority.defaultLow
heightConstraint.isActive = true
titleView.translatesAutoresizingMaskIntoConstraints = false
titleView.topAnchor.constraint(equalTo: ImageView.bottomAnchor).isActive = true
titleView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
titleView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
titleView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
titleView.numberOfLines = 0
// titleView.text = " "
如果您完全删除有关titleView
的代码并希望在单元格中拥有一个具有动态高度的UIImageView
,请为imageView
添加bottomAnchor
约束
class MyCellView: UITableViewCell
private let ImageView = UIImageView()
private let titleView = UILabel()
override init(style: UITableViewCellStyle, reuseIdentifier: String?)
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(ImageView)
contentView.addSubview(titleView)
ImageView.translatesAutoresizingMaskIntoConstraints = false
ImageView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
ImageView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
ImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
ImageView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
let heightConstraint = ImageView.heightAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.6)
heightConstraint.priority = UILayoutPriority.defaultLow
heightConstraint.isActive = true
【讨论】:
我按照你的建议添加了这行代码,仍然有约束警告。 @JoeHuang 我已经更新了我的答案,你可以再次查看。【参考方案2】:这似乎是一个已知“错误”的结果 - tableView
设置的高度与自动布局计算的高度发生冲突。渲染单元格时,tableView
首先应用默认高度,计算自动布局高度,然后使用后者 - 至少看起来如此。见我的question。
这意味着您使用的约束是可以的(至少在我看来是这样)。只需将定义高度的约束之一设置为priority = 999(这样在停用默认高度约束之前不会导致任何冲突)。最终,无论如何都会导致使用你的约束,所以不会造成任何麻烦。
P.S.:注意 imageView 的高度限制:
ImageView.heightAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.6).isActive = true
如果您想省略图像(因此将其渲染为高度 = 0),那也会给您带来麻烦(同样,降低优先级可能会让您到达您想要的位置)。如果图像总是在那里,那就别管我的 P.S. :)。
【讨论】:
以上是关于如何为具有动态高度的表格单元格正确设置自动布局?的主要内容,如果未能解决你的问题,请参考以下文章
滚动时 UITableViewCell 自动布局抖动的动态单元格高度问题