Reputation: 270810
I am writing an iOS card game. I want to show the user the cards in his hand. I looked for CocoaPods that does this in a good-looking way, but couldn't find any, so I decided to create such a view myself using a horizontal UICollectionView
.
Here are some requirements:
This is my attempt:
I added constraints for the collection view and the image view in the prototype cell in the storyboard. Then I added this code.
extension ViewController : UICollectionViewDataSource, UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 15
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
cell.addConstraint(NSLayoutConstraint(item: cell, attribute: .height, relatedBy: .equal, toItem: cell, attribute: .width, multiplier: 5.0 / 7.0, constant: 0))
// here I am just setting all the cells to have the same image for testing purposes
(cell.viewWithTag(1) as! UIImageView).image = someCardImage
return cell
}
}
Result:
Only the collection view's constraints seem to be working. Everything else isn't. The aspect ratio constraint I added programmatically above apparently conflicts with some other constraint that I am not aware of:
[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:0x604000290810 UICollectionViewCell:0x7fd536610300.height == 0.714286*UICollectionViewCell:0x7fd536610300.width (active)>",
"<NSLayoutConstraint:0x600000292390 'UIView-Encapsulated-Layout-Height' UICollectionViewCell:0x7fd536610300.height == 99 (active)>", <---- What is this constraint?
"<NSLayoutConstraint:0x600000292340 'UIView-Encapsulated-Layout-Width' UICollectionViewCell:0x7fd536610300.width == 68 (active)>" <---- What is this constraint?
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600000292390 'UIView-Encapsulated-Layout-Height' UICollectionViewCell:0x7fd536610300.height == 99 (active)>
And the image views' are not completely filling the whole cell, as seen in the UI hierarchy:
How do I create such a collection view, satisfying my requirements?
Upvotes: 1
Views: 475
Reputation: 270810
I figured this out after a bit more looking around on the internet.
Apparently, there is this method called collectionView(_:layout:sizeForItemAt:)
in CollectionViewDelegateFLowLayout
. This is the first time that I know this method existed!
If I override that method, I can set the size of the cells however I want:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height = collectionView.height
let width = height * 5 / 7
return CGSize(width: width, height: height)
}
So the constraint I programmatically added isn't needed after all.
For the image view's frame problem, I solved it by trial and error. I unchecked this "relative to margin" option in the constraint's property inspector:
My guess is that the "margin" of the cell is 8 pixels, so setting it relative to the margin leaves out 8 pixels of space.
Upvotes: 1