Unome
Unome

Reputation: 6900

How to make a button half the width of a UITableViewCell using constraints (Storyboard or Programatically)

I have a project I'm working on that needs two buttons with some data that will take up exactly half the width of the UITableViewCell that they are in.

In the past when I have wanted to do this I usually set a constraint that the button will be equal widths to its superview and give it a multiplier of 0.5.

For some reason however inside the UITableViewCell I can't get the Storyboards to give me this option. The "Equal Widths" constraint in the GUI is grayed out.

Example of what I'm trying to achieve

I resolved to just do it programmatically so in the custom cell I tied the following code. I've tried putting the cellInit() method below being called in the awakeFromNib and that gave an error. I've tried also just calling it on cellForRowAtIndexPath when the cell is loaded, and got the same error.

import UIKit

class PollCell: UITableViewCell {

@IBOutlet weak var option1: UIButton!
@IBOutlet weak var option2: UIButton!

override func awakeFromNib() {
    super.awakeFromNib()

    //cellInit() //Commented out because causes error
}

func cellInit(){
    option1.addConstraint(NSLayoutConstraint(item: option1, attribute: .Width, relatedBy: .Equal, toItem: self, attribute: .Width, multiplier: 0.5, constant: 0))
}

}

This is the error that I am getting:

'NSInternalInconsistencyException', reason: 'Impossible to set up layout with view hierarchy unprepared for constraint.

What I'm trying to achieve is pretty standard, so I assume this isn't anything to crazy and I'm probably doing something the wrong way. Either way I assume plenty of newcomers like myself will run into this. Thanks in advance!

Upvotes: 3

Views: 1949

Answers (2)

ericgu
ericgu

Reputation: 2249

In the comments, we discussed that you leverage contentView.frame.maxX

Alternatively, you can use AutoLayout: Make sure you setTranslatesAutoresizingMaskIntoConstraints(false)

Assign tags (optional). You only havetwo buttons but for more than two, I would use tags so you don't need to manually type UIButton for every button.

addConstraint(NSLayoutConstraint(item: self.viewWithTag(1) as UIButton, attribute: .Right, relatedBy: .Equal, toItem: self, attribute: .CenterX, multiplier: 0.33, constant: 0))
addConstraint(NSLayoutConstraint(item: self.viewWithTag(2) as UIButton, attribute: .Right, relatedBy: .Equal, toItem: self, attribute: .CenterX, multiplier: 0.66, constant: 0))

OR VFL using a Dictionary:

for button in buttonsDictionary.keys {
          self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[\(button1)]-[\(button2)]|", options: .allZeros, metrics: nil, views: buttonsDictionary))
        }

call cell.updateConstraints() in your cellForRowAtIndexPath in TableView.

You can learn more in the link below: They have an example of two side by side buttons:

https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/AutoLayoutinCode/AutoLayoutinCode.html#//apple_ref/doc/uid/TP40010853-CH11-SW1

Upvotes: 1

Sean
Sean

Reputation: 1534

I've encountered a similar problem like yours before. What I did was put a UIView in the cell first with its top, left, right, bottom constraints set to all 0, then place the button on top of the view. This way I get the 'equal width' option.

Upvotes: 1

Related Questions