I'm following this tutorial:
Basically a horizontal collectionView
in section 1
and a vertical collectionView
in section 2
My thought was putting a collectionView inside the first cell, which should have the size: CGSize(width: screen.width, height: 100)
But since I'm using the method from the link, I don't know how to give a specific size for the first cell. This is what I've tried:
CodePudding user response:
Disclaimer: As OP had asked a question earlier on how to create a Pinterest layout and I had suggested Raywenderlich tutorial in comments, I believe this question from OP is extension of that
Answer:
Looking at the design you added, I believe you are trying to add a CollectionView
with a horizontal scroll as the first cell which spans the entire collection view width. Because you have subclassed the UICollectionViewFlowLayout
you need to handle this special case in prepare
method itself
override func prepare() {
// 1
guard
cache.isEmpty,
let collectionView = collectionView
else {
return
}
// 2
let columnWidth = contentWidth / CGFloat(numberOfColumns)
var xOffset: [CGFloat] = []
for column in 0..<numberOfColumns {
xOffset.append(CGFloat(column) * columnWidth)
}
var column = 0
var yOffset: [CGFloat] = .init(repeating: 0, count: numberOfColumns)
// 3
for item in 0..<collectionView.numberOfItems(inSection: 0) {
let indexPath = IndexPath(item: item, section: 0)
let attributes: UICollectionViewLayoutAttributes
let photoHeight = delegate?.collectionView(
collectionView,
heightForPhotoAtIndexPath: indexPath) ?? 180
let height = cellPadding * 2 photoHeight
let frame: CGRect
if item == 0 {
frame = CGRect(x: 0,
y: yOffset[column],
width: columnWidth,
height: height)
contentHeight = frame.maxY
for column in 0..<numberOfColumns {
yOffset[column] = frame.maxY
}
column = 0
}
else {
// 4
frame = CGRect(x: xOffset[column],
y: yOffset[column],
width: columnWidth,
height: height)
contentHeight = max(contentHeight, frame.maxY)
yOffset[column] = yOffset[column] height
column = column < (numberOfColumns - 1) ? (column 1) : 0
}
let insetFrame = frame.insetBy(dx: cellPadding, dy: cellPadding)
attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
attributes.frame = insetFrame
cache.append(attributes)
}
}
In your for item in 0..<collectionView.numberOfItems(inSection: 0) {
I have added a special condition for handling if item == 0 {
where in instead of using column width, I have used content width (as per your design you want first cell to cover the whole width of collection view)
Finally in your delegate method
extension PhotoStreamViewController: PinterestLayoutDelegate {
func collectionView(
_ collectionView: UICollectionView,
heightForPhotoAtIndexPath indexPath:IndexPath) -> CGFloat {
if indexPath.row == 0 {
return 180 // whatever is the height of first cell
}
return photos[indexPath.item].image.size.height
}
}
A word of caution
In your design I can see that you have added two section headers Header 1 and Header 2 I guess in that case your returning number of sections as at least 2, but the tutorial focuses on a single section collection view, if you notice
for item in 0..<collectionView.numberOfItems(inSection: 0) {
section 0 is hard coded, you might have to handle it dynamically if you wanna handle multiple sections and might need a lot of reworking around prepare
CodePudding user response:
A strategy you might follow to gain the ability to control the size of your collection items is to have your delegate for the UICollection
view derive from UICollectionViewDelegateFlowLayout
instead of just from UICollectionViewDelegate
. By deriving from UICollectionViewDelegateFlowLayout
your delegate can implement:
func collectionView(UICollectionView, layout: UICollectionViewLayout, sizeForItemAt: IndexPath) -> CGSize
And tell the system the size of the first item.