I'm attempting to build a table view, who's cells contain cards that are horizontally scrolled. I created a simple demo-app and have had success in implementing a version that uses Auto Layout... to a certain extent. One (I believe to be final) issue remains. The vertical sizing of the cards is bugged.
TableView:
class MultiCardTableViewController: UITableViewController {
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 12
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CardCell", forIndexPath: indexPath) as CardCell
//since these cells are re-used, we have to clear out the previous dynamic subviews
for subView in cell.scrollContentView.subviews { subView.removeFromSuperview() }
var card = NSBundle.mainBundle().loadNibNamed("CardView", owner: self, options: nil)[0] as CardView
//Turn this off because subviews of UIScrollView use autoresizing mask by default, which conflict with Auto-Layout constraints
card.setTranslatesAutoresizingMaskIntoConstraints(false)
cell.scrollContentView.addSubview(card)
var card2 = NSBundle.mainBundle().loadNibNamed("CardView", owner: self, options: nil)[0] as CardView
//Turn this off because subviews of UIScrollView use autoresizing mask by default, which conflict with Auto-Layout constraints
card2.setTranslatesAutoresizingMaskIntoConstraints(false)
cell.scrollContentView.addSubview(card2)
//Add bottom margin to the last cell (for consistency)
//Add vertical constraints (standard margins) for each card
var constraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|-[card]|", options: nil, metrics: nil, views: ["card": card])
constraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|-[card2]|", options: nil, metrics: nil, views: ["card2": card2])
//Add horizontal constraints that tie the cards together, and to the super view
constraints += NSLayoutConstraint.constraintsWithVisualFormat("H:|-[card]-(16)-[card2]-|", options: nil, metrics: nil, views: ["card": card, "card2": card2])
//Add horizontal constraint that disambiguates individual card width
constraints += NSLayoutConstraint.constraintsWithVisualFormat("H:[card(==card2)]", options: nil, metrics: nil, views: ["card": card, "card2": card2])
cell.scrollContentView.addConstraints(constraints)
//Set the scrollview content horizontal size constraint to double the window width (1 window width for each card
cell.contentWidthConstraint.constant = self.tableView.frame.width * 2
return cell
}
}
Cell:
class CardCell: UITableViewCell
{
@IBOutlet weak var scrollView: UIScrollView!
//A content view directly inside of the scroll view, constrained to super view on all sides, as well as height & width
@IBOutlet weak var scrollContentView: UIView!
//A reference to the width constraint for the scrollContentView
@IBOutlet weak var contentWidthConstraint: NSLayoutConstraint!
}
CardView.xib:
Result:
The horizontal spacing and sizing is correct, but it appears that the vertical constraints are insufficient or incorrect. I find this hard to believe because they are so simple. Each card has the vertical constraint: V:|-[card]|
I've tried adding an explicit height constraint on the cards, similar to the width, but this also doesn't produce correct results: V:[card(==card2)]
Result of explicit vertical height constraint:
I've been wracking my brains for days... What am I missing?
Edit: Added github source link for the sample project
Fortunately the issue was a minor typo in my code example above:
constraints = NSLayoutConstraint.constraintsWithVisualFormat("V:|-[card2]|", options: nil, metrics: nil, views: ["card2": card2])
Is overwriting the previous constraints array, and should add to it instead:
constraints += NSLayoutConstraint.constraintsWithVisualFormat("V:|-[card2]|", options: nil, metrics: nil, views: ["card2": card2])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With