1

I have a collection view of image views, and when run in the simulator on an iPhone 7, the layout is how I want it - images displayed 3 per line, with no spacing in between. However when I run it on my phone (iPhone 6+), there is spacing between the images.

These are the functions that set up the layout:

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

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
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    let imgWidth = view.bounds.width/3.0
    let imgHeight = imgWidth

    return CGSize(width: imgWidth, height: imgHeight)
}

I was thinking that sizeForItem would re-scale the images by stating that the width would be the screen width divided by three, and the height equal to that. But I think I'm confused about that and perhaps it's only resizing the cell, and not the image view within. However I'm not sure where I can set the image view size to scale dynamically with the screen size.

How can I change it so the image cells in the collection view resize themselves accordingly, and remain 3 per line with no spacing, regardless of screen size?

EDIT: After putting cell.postImage.contentMode = UIViewContentMode.scaleAspectFill into cellForItem method:

enter image description here

EDIT 2: After trying iOSFreak's solution, problem still persists:

enter image description here

KingTim
  • 1,281
  • 4
  • 21
  • 29
  • Are you using `myImageView.contentMode = UIViewContentModeScaleAspectFill` ? – Zhang Mar 11 '17 at 14:15
  • I have the image view content mode set to scale to fill in storyboard. However when I tried your advice and added ` cell.postImage.contentMode = UIViewContentMode.scaleAspectFill` to my `cellForItem` method, it fixed the problem somewhat, but not entirely - now some the cells are aligned correctly side-by side, but one of them has space on the side. And there is still space between the first and second row. I'll try to upload a pic. – KingTim Mar 11 '17 at 14:28
  • I edited my post to show what I see now. – KingTim Mar 11 '17 at 14:31
  • Are you creating the cell programmatically and adding subviews or in storyboard? – agibson007 Mar 11 '17 at 22:59
  • Is your collectionview's layout pinned to all four sides of your viewcontroller's view or is your collectionview actually wider than your viewcontroller's view? Set your collectionview interim line spacing and cell spacing to 0. Use `let imgWidth = UIScreen.main.bounds.size.width/3.0`. – Zhang Mar 12 '17 at 02:03
  • Here is the solution: https://stackoverflow.com/questions/56840665/why-on-xcode-11-uicollectionviewcell-changes-size-as-soon-as-you-scroll-i-alre – vipintklm Oct 01 '20 at 12:20

3 Answers3

11

You change Estimate Size "None".

enter image description here

ikbal
  • 1,110
  • 12
  • 21
2

Provided you have the imageview pinned to the collection view cell using autolayout cell 0-top,0-bottom,0-leading, and 0-trailing or autoresizing of .flexible height and .flexible width I don't see why it would not work in your example. Your methods look right.

Do you have UICollectionViewDelegateFlowLayout in the declarations example?

class ViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {}
agibson007
  • 4,173
  • 2
  • 19
  • 24
  • This ended up being it - I hadn't set autolayout on the image view in the collection view. Once I added that, I went back to my original code and everything looked good. – KingTim Mar 12 '17 at 15:09
0

Please try the below code

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

  let imgWidth = CGRectGetWidth(collectionView.frame)/3.0
  return CGSize(width: imgWidth, height: imgWidth)
}

if this doesn't work, Create a subClass of UICollectionViewFlowLayoutas shown below

Updated to swift 3.0

class CustomImageLayout: UICollectionViewFlowLayout {

var numberOfColumns:CGFloat = 3.0

override init() {
    super.init()
    setupLayout()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    setupLayout()
}

override var itemSize: CGSize {
    set { }
    get {
        let itemWidth = (self.collectionView!.frame.width - (self.numberOfColumns - 1)) / self.numberOfColumns
        return CGSize(width: itemWidth, height: itemWidth)
    }
}

func setupLayout() {
    minimumInteritemSpacing = 1 // Set to zero if you want
    minimumLineSpacing = 1
    scrollDirection = .vertical
}
}

You need set collection views layout with custom layout.

class ViewController: UIViewController {

    @IBOutlet weak var colleciton: UICollectionView!

override func viewDidLoad() {
    super.viewDidLoad()
    colleciton.collectionViewLayout = CustomImageLayout()
    // Do any additional setup after loading the view, typically from a nib.
}
}

Please find attached image of working code!

Venkat057
  • 187
  • 9
  • The first approach resulted in the same thing that I posted in my edit, and I had to change the second approach a bit (CGSizeMake has been deprecated so I made a frame: `let frame = CGSize(width: itemWidth, height: itemWidth)` and did `return CGSize(dictionaryRepresentation: frame as! CFDictionary)!` to get rid of the errors. And that resulted in spacing between all of the cells, even when setting `minimumInterlineSpacing` to 0. – KingTim Mar 11 '17 at 15:04
  • I just tried your edited version for Swift 3, and the images still aren't arranged properly - there's spacing between the rows, and certain images have space on the sides as well. I posted a second edit with an updated picture. – KingTim Mar 11 '17 at 15:41
  • I will add, I'm not sure how this is affecting things, but four of the pics in my second edit were taken from my phone's camera (the cat, the raspberry pi, and the two photos of my screen), while the rest were uploaded from my camera roll, and were just stock photos downloaded from the internet. But the image view in storyboard is set to scale to fill, regardless of the origin of the photo so again I'm not exactly sure why only the photos taken by my phone have spacing on the sides, while the internet pics don't. – KingTim Mar 11 '17 at 15:44
  • The code I have posted working fine for me, I am also showing images in cells same as your screenshots. I suppose there is some problem with the way you are displaying images. Try image content mode to aspect to fill or post your code. – Venkat057 Mar 11 '17 at 15:48
  • In my storyboard, I have the image view set to "aspect fill" in attributes inspector, then also have `cell.postImage.contentMode = UIViewContentMode.scaleAspectFill` in my `cellForItem` method - not sure if that's redundant doing it in both places, but anyway the images as you can see still aren't quite right. Not sure how else I can change that. – KingTim Mar 11 '17 at 15:57
  • Try UI debugger and check image view frame for cell as well as cell content view frame. – Venkat057 Mar 11 '17 at 16:26