I have a dynamic collectionView, and essentially the spacing between cells needs to be the same regardless the width of the cell.
Found similar answers here and on the internet, but all were for vertical scrolling collectionViews. So, I went on and tried to work further on one of those answers to achieve what I want, with no much luck.
Currently, my collectionView has the same spacing between cells, but after each cell, it moves to the next row, although I'm not changing or manipulating the y offset of the attributes. Also, not all cells are visible.
Please, can you point out what I'm doing wrong? Thanks.
The subclass of UICollectionViewFlowLayout that I'm using is:
class TagsLayout: UICollectionViewFlowLayout {
let cellSpacing: CGFloat = 20
override init(){
super.init()
scrollDirection = .horizontal
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
self.scrollDirection = .horizontal
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
guard let attributes = super.layoutAttributesForElements(in: rect) else {
return nil
}
guard let attributesToReturn = attributes.map( { $0.copy() }) as? [UICollectionViewLayoutAttributes] else {
return nil
}
var leftMargin = sectionInset.left
var maxX: CGFloat = -1.0
attributesToReturn.forEach { layoutAttribute in
if layoutAttribute.frame.origin.x >= maxX {
leftMargin = sectionInset.left
}
layoutAttribute.frame.origin.x = leftMargin
leftMargin += layoutAttribute.frame.width + cellSpacing
maxX = max(layoutAttribute.frame.maxX , maxX)
}
return attributesToReturn
}
}

As I said in my comment, you are using code for a "left-aligned vertical scrolling" collection view.
A horizontal scrolling collection view lays out the cells like this:
your code is calculating a new
origin.xfor each cell in sequence, resulting in this:You could modify your custom flow layout to keep track of a
maxXfor each "row" ... but, if you have a lot of cells as soon as you scroll so the first few "columns" are out-of-view, those cells will no longer be factored into the layout.So, you could attempt to "pre-calculated" the frame widths and x-origins of all your cells, and get close to your goal:
Two more issues though...
First, assuming your cells contain longer strings than shown in these images, the collection view doesn't do a good job of figuring out which cells actually need to be shown. That is, the collection view will use the estimated items size to decide if a cell will need to be rendered. If the modification to the cells
origin.xvalues would not fall within the expected range, certain cells will not be rendered because the collection view won't ask for them.Second, if you have varying-width tags, you could end up with something like this:
and rotated to landscape for emphasis (the top row actually goes all the way to 24):
You may want to re-think your approach and either go with a vertical-scrolling left-aligned collection view, or a horizontal-scrolling collection view with equal-width cells, or some other approach (such as a normal scroll view with subviews laid-out via your own code).
I did create classes using the "pre-calculate" approach -- here they are if you want to give it a try.
Simple cell with a label:
Modified custom flow layout:
Example controller class with generated tag strings:
Note that this is Example Code Only!!! It has not been tested and may or may not fit your needs.