0

My goal is to show the yellow tags inline until it fills the available width, then goes to the next line.

I used UICollectionView Flow Layout to achieve that. Here is my full code stripped down to the minimum reproducible example.

What you see on Image 1 is what appears on view did load.

The problem is that the 5th yellow tag could have been placed in the same line as the others because there is enough space. What should I do with my code to achieve the image shown in image 2 ?

Weirdly, after I reload the UICollection view, the layout appears as expected on image 2. You can achieve Image 2 by clicking on the remove button once then add button once.

Along with the fix, I would appreciate a small explanation because I have spent several hours on this issue, tried so many things but nothing works.

This is the code to resize the height of the collection view.

  let layoutHeight = collectionView.collectionViewLayout
            .collectionViewContentSize.height
        collectionViewHeight.constant = layoutHeight

This is the code to size the item cells:

 func collectionView(_: UICollectionView,
                        layout _: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {
        let string = tagList[indexPath.row]
        let fontAttribute = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 18, weight: .regular)]
        
                  let stringSize = string.size(withAttributes: fontAttribute)
                  let padding: CGFloat = 25
                  let width = stringSize.width + padding
        return CGSize(width: width, height: 50)
       
    }

Image 1 (wrong, the 5th cells should be to the right of the 4th, not below)

enter image description here

Image 2 (Right, expected behaviour, can be achieved but reloading the collection view)

enter image description here

TSR
  • 17,242
  • 27
  • 93
  • 197
  • To understand the issue: Add in `setup(tagList:)`: `print("TableViewCell for Tag size: \(self.frame.size)")`, the first time, it will be 313, because that's the size in the xib `TagsCell`. The collection will render with that siize, and that's why the last tag doesn't fit. Then, autolayout is applied, and the TagCell frame changes, the collection view frame too, but then the attributes have already been set and aren't not updated. When you reload the tableview, the width is correct, and the last tag is shown correctly. That's for the explanation on how it works. – Larme Mar 28 '22 at 17:48
  • Thank you for checking this issue. I understand that I need to find a way to make the collection view frame reload after the autolayout is done. I tried to use DispatchQueue.asyncAfter 600 ms to verify and it works, That could work as a work around. I would appreciate if you know of a better solution (something buitlin like a callback function or method to override to listen to that autolayout completion) – TSR Mar 28 '22 at 18:08
  • In my main project, I added this fix https://stackoverflow.com/a/27148268/6727914 plus a first call to set the height then a second call inside main.async to set the height again – TSR Mar 28 '22 at 19:13
  • The issue you are hitting is the fact that when you load your collection view, its frame has not yet been set... so its width is not as wide as the cell. Since you are not using the benefits of a `UICollectionView` (memory management via cell reuse, auto scrolling, etc), and you are taking the opposite approach (you're setting the collection view height based on its cells, instead of letting the collection view layout the cells), I'd suggest using something else. Take a look at this for one option: https://stackoverflow.com/a/60588546/6257435 – DonMag Mar 28 '22 at 20:08

0 Answers0