0

Width/height of my UICollectionView matches all available space.

I want to display two cells in one row (two columns)

So width of one cell should take half width of UICollectionView (collectionView.frame.width / 2)

So I programmatically change width of cell in function of UICollectionViewDelegateFlowLayout:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: collectionView.frame.width / 2.0, height: 150)
}

But visually width of cell is much bigger than collectionView.frame.width / 2.0 (tested on iPhone SE simulator)

So it takes more than half-width space of screen

Here I printed info about sizes:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath)
    print("didSelectItemAt \(cell.frame.width), table width: \(collectionView.frame.width), item calc width: \(collectionView.frame.width / 2)")
}

didSelectItemAt cell width 187.5, table width: 375.0, half-width: 187.5

enter image description here

Why does it happen?

There is also an issue with margins but first I have to solve this one

Update

Though it works fine with iPhone 6s Simulator (I edited image to place two items in the first row to check if they fit):

enter image description here

So what is wrong with iPhone SE?

I don't want to find out that there can be the same issue with other iPhones or iPads too

user924
  • 8,146
  • 7
  • 57
  • 139
  • Please check this it's working fine remove all code which you have write and do it step by step https://stackoverflow.com/a/54703798/10150796 – Nikunj Kumbhani Mar 29 '19 at 09:20
  • In my tests, when `sizeForItemAt` delegate method runs, it's *too early* and `collectionView.frame.width` still wrongly reports the design-time size, the one taken from Interface Builder with its current set device. So when running on a (simulated) different device you can see the issue, as calculation is wrong. Did you experience this as well? – superjos Feb 12 '20 at 16:44

4 Answers4

2

375.0 is the size of iPhone 6s and X, not iPhone SE which is 320.0

The reason is there is a width constraint of collectionView which was set at iPhone 6s mode but later when switching to the SE simulator, this constraint was not updated.

E.Coms
  • 11,065
  • 2
  • 23
  • 35
  • ok, I'll check constraint later. For `UICollectionView` I previously set `trailing, leading, top, bottom` to `safe area` – user924 Mar 29 '19 at 07:41
  • I use auto layout, I believe constraints should work the same way for all devices – user924 Mar 29 '19 at 11:24
  • Maybe. But you have to double check on different design mode. – E.Coms Mar 29 '19 at 11:41
  • Found the issue. If we add Collection View Controller to storyboard it works ok only for the current selected iPhone device... So annoying I had to manually add constraints to make Collection View fit Safe Area of any device – user924 Apr 12 '19 at 19:23
0

I think there is problem of cell spacing. it seems there is default cell spacing exists in your implementation. you should try below code to adjust two cell in one raw of collectionview:

extension ViewController : UICollectionViewDelegateFlowLayout{

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let collectionViewWidth = collectionView.bounds.width
        return CGSize(width: collectionViewWidth/2, height: 150)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }
}

moreover, you should check constraint of your UICollectionView if it is as per your requirement Or not.

Dhaval Bhimani
  • 980
  • 1
  • 13
  • 24
0

Try to use the wide from the view, not the collectionView.

Try this:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: (view.frame.width / 2.0) - 5, height: 150) // provide little bit space between cells
}

Hope this will help.

Faysal Ahmed
  • 7,501
  • 5
  • 28
  • 50
0

The best solution is, to reload your collection view in main thread with a bit delay.

   DispatchQueue.main.asyncAfter(deadline: .now() + 0.10) {
       self.myCollectionView.reloadData()
   }
Vinodsagar
  • 11
  • 2