如何为具有动态高度的表格单元格正确设置自动布局?

时间:2017-12-22 07:31:02

标签: ios swift uitableview

我尝试创建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.

2 个答案:

答案 0 :(得分:2)

这似乎是已知“bug”的结果 - )设置的高度与自动布局计算的高度发生碰撞。渲染单元格时,tableView首先应用默认高度,计算自动布局高度,然后使用后者 - 至少看起来如此。查看我的question

这意味着您使用的约束条件正常(至少它们对我来说似乎如此)。只需将其中一个约束定义为priority = 999(这样直到它停用默认高度约束它不会导致任何冲突)。最后,无论如何都会导致使用你的约束,所以它不会造成任何麻烦。

P.S。:注意该imageView高度约束:

tableView

如果你想省略图像(因此用高度= 0渲染它),那也会给你带来麻烦(再次,降低优先级可能会让你到达你想要的地方)。如果图像总是在那里,那么永远不要我的P.S. :)

答案 1 :(得分: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,则为bottomAnchor添加imageView约束

    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
      }
    }