Search code examples
iosuitableviewswiftautolayoutvisual-format-language

Autolayout - Vertically center two views in a UITableViewCell when one view has dynamic height


target

This is what I'm trying to achieve. Inside of a UITableView Cell, I have a UIlabel populated with dynamic content and a separate UIView that has a set height. In some cases the when there is a lot of text, the UIlabel determines the height of the UITableView Cell. In other cases when there is only one line of text populating the UILabel, the UIView sets the height of the cell. (This is what I currently have.)

    self.myLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
    self.myView.setTranslatesAutoresizingMaskIntoConstraints(false)


    let viewsDictionary = [
        "myLabel":myLabel,
        "myView":myView,
    ]


    let myLabel_H:Array = NSLayoutConstraint.constraintsWithVisualFormat("H:|-15-[myLabel]-60-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
    let myLabel_V:Array = NSLayoutConstraint.constraintsWithVisualFormat("V:|-[myLabel]-|", options:NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)

    self.contentView.addConstraints(myLabel_H)
    self.contentView.addConstraints(myLabel_V)


    let myView_H:Array = NSLayoutConstraint.constraintsWithVisualFormat("H:[myView(50)]-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
    let myView_V:Array = NSLayoutConstraint.constraintsWithVisualFormat("V:|-(>=10)-[myView(100)]-(>=10)-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)

    self.contentView.addConstraints(myView_H)
    self.contentView.addConstraints(myView_V)

Instead I get this: (And I'm throwing errors: =10)-| (Names: '|':UITableViewCellContentView:0x7fc21bc6d050 )>)

current


Solution

  • You can align your two subviews using the alignment values in the options parameter of the visual layout method (.AlignAllCenterY), so you don't need to add a separate constraint for the image view to center it in the y direction. Also, it would be better to make the horizontal constraints go from the left edge to the label to the image view to the right edge, instead of pinning the label to both edges of the superview.

    class RDTableViewCell: UITableViewCell {
    
        var myLabel = UILabel()
        var myView = UIImageView()
    
        required init(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
    
        override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
    
            myLabel.numberOfLines = 0
            myLabel.setTranslatesAutoresizingMaskIntoConstraints(false)
            myView.setTranslatesAutoresizingMaskIntoConstraints(false)
    
            contentView.addSubview(myLabel)
            contentView.addSubview(myView)
    
            let viewsDictionary = ["myLabel":myLabel, "myView":myView]
    
            let horizontalCons = NSLayoutConstraint.constraintsWithVisualFormat("H:|-15-[myLabel]-[myView(50)]-|", options: .AlignAllCenterY, metrics: nil, views: viewsDictionary)
            let myLabel_V = NSLayoutConstraint.constraintsWithVisualFormat("V:|-[myLabel]-|", options:NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
            let myView_V = NSLayoutConstraint.constraintsWithVisualFormat("V:|-(>=10)-[myView(100)]-(>=10)-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDictionary)
    
            contentView.addConstraints(horizontalCons)
            contentView.addConstraints(myLabel_V)
            contentView.addConstraints(myView_V)
        }
    }