3

I have a UICollectionView that displays 12 images. The images are not fitting in the cells, they are being cropped, but I want them to fit in the cells without being cropped.

The code that should make the image scale to fit is:

 cell.imageView.contentMode = UIViewContentMode.ScaleAspectFit
 cell.imageView.image = UIImage(named: name)

Here is my code for the whole viewController class and screenshot:

import UIKit

class DressingRoomViewController:
        UIViewController,
        UICollectionViewDelegateFlowLayout,
        UICollectionViewDataSource {

    @IBOutlet weak var collectionView: UICollectionView!

    let identifier = "cellIdentifier"
    let dataSource = DataSource()

    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.dataSource = self
    }

    override func viewDidAppear(animated: Bool) {
        //  Notes on the equation to get the cell size:
        //  cells per row = 6
        //  cell spacing = 10
        //  collectionView.layout.inset = 20 (10 left, 10 right)
        let cellSize = (collectionView.collectionViewLayout
            .collectionViewContentSize().width - 20) / 6 - 10

        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()

        layout.sectionInset = UIEdgeInsets( top: 20,
                                            left: 10,
                                            bottom: 10,
                                            right: 10)

        layout.itemSize = CGSize(width: cellSize, height: cellSize)

        collectionView.collectionViewLayout = layout
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    override func prepareForSegue(  segue: UIStoryboardSegue,
                                    sender: AnyObject?) {
        if (segue.identifier == "dressingRoom2MyOutfits") {
            let myOutfitsViewController = segue.destinationViewController
                as! MyOutfitsViewController
        }
    }
}



// MARK:- UICollectionViewDataSource Delegate
extension DressingRoomViewController : UICollectionViewDataSource {

    func numberOfSectionsInCollectionView(
        collectionView: UICollectionView) -> Int {
            return 1
    }

    func collectionView(collectionView: UICollectionView,
        numberOfItemsInSection section: Int) -> Int {
            return 12
    }

    func collectionView(collectionView: UICollectionView,
        cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(
            identifier,forIndexPath:indexPath) as! FruitCell

        let fruits: [Fruit] = dataSource.fruits
        let fruit = fruits[indexPath.row]

        let name = fruit.name!

        cell.imageView.contentMode = UIViewContentMode.ScaleAspectFit
        cell.imageView.image = UIImage(named: name)

        return cell
    }
}

EDIT: Here is the FruitCell class, just in case you were wondering.

    class FruitCell: UICollectionViewCell {

    @IBOutlet weak var imageView: UIImageView!

}

enter image description here

BeniaminoBaggins
  • 11,202
  • 41
  • 152
  • 287
  • Change content mode of uiimageview . Here is the link : http://stackoverflow.com/questions/14134035/how-to-manage-uiimageview-content-mode – Mihir Oza Aug 25 '15 at 08:13
  • @MihirOza I am already changing the contentMode of UIImageView. So I tried adding the autoresizingMask of UIImageView but that did nothing. – BeniaminoBaggins Aug 25 '15 at 08:22
  • Isn't this just a repetition of your earlier http://stackoverflow.com/questions/32194205/uicollectionview-cells-do-not-take-up-width-of-uicollectionview ? – matt Aug 25 '15 at 22:39
  • @matt No, I have already solved the previous question as you can see I have the 6 columns in my CollectionView. This question is about the images inside the cells being cropped which is not what I want. – BeniaminoBaggins Aug 25 '15 at 22:44
  • "I have already solved the previous question" Actually I believe _I_ solved it. But never mind... So is the problem here that you don't understand how an image view works, or do you want to redraw the original images themselves down to scale? – matt Aug 25 '15 at 22:46
  • @matt I want to draw the images down to scale. Keeping the cell the same size. The thing that will change size is the image, fitting to the size of the cell. – BeniaminoBaggins Aug 25 '15 at 22:50
  • My book teaches you how to draw an image down to scale: http://www.apeth.com/iOSBook/ch15.html#_uiimage_drawing – matt Aug 26 '15 at 00:08

1 Answers1

3

A UIImageView that has been placed in a UICollectionViewCell from the interface builder, will not have any knowledge of a UICollectionViewFlowLayout that has been initialised programmatically. So the layout.sectionInset that I had set, was making the UICollectionViewCells smaller, and even when the UIImageView created in interface builder was constrained to the margins of the UICollectionViewCell, the UIImageView was not resizing to go smaller.

The solution was to initialise the UIImageView programmatically and set the size to be the size of the cell taking into account the cell spacing.

Here is the code:

import UIKit

class DressingRoomViewController:
        UIViewController,
        UICollectionViewDelegateFlowLayout,
        UICollectionViewDataSource {

    @IBOutlet weak var collectionView: UICollectionView!

    let identifier = "cellIdentifier"
    let dataSource = DataSource()
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    let cellSpacing: CGFloat = 2
    let cellsPerRow: CGFloat = 6


    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.dataSource = self
    }

    override func viewDidAppear(animated: Bool) {
        let cellSize = (collectionView.collectionViewLayout
            .collectionViewContentSize().width / cellsPerRow) - (cellSpacing)

        layout.itemSize = CGSize(width: cellSize, height: cellSize)
        layout.minimumInteritemSpacing = cellSpacing
        layout.minimumLineSpacing = cellSpacing
        collectionView.collectionViewLayout = layout
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    override func prepareForSegue(  segue: UIStoryboardSegue,
                                    sender: AnyObject?) {
        if (segue.identifier == "dressingRoom2MyOutfits") {
            let myOutfitsViewController = segue.destinationViewController
                as! MyOutfitsViewController
        }
    }
}



// MARK:- UICollectionViewDataSource Delegate
extension DressingRoomViewController : UICollectionViewDataSource {

    func numberOfSectionsInCollectionView(
        collectionView: UICollectionView) -> Int {
            return 1
    }

    func collectionView(collectionView: UICollectionView,
        numberOfItemsInSection section: Int) -> Int {
            return 12
    }

    func collectionView(collectionView: UICollectionView,
        cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(
            identifier,forIndexPath:indexPath) as! FruitCell

        let fruits: [Fruit] = dataSource.fruits
        let fruit = fruits[indexPath.row]

        let name = fruit.name!

        var imageView :UIImageView
        imageView = UIImageView(frame:CGRectMake(   0,
                                                    0,
            (collectionView.collectionViewLayout
                .collectionViewContentSize().width / cellsPerRow)
                - (cellSpacing),
            (collectionView.collectionViewLayout
                .collectionViewContentSize().width / cellsPerRow)
                - (cellSpacing)))

        imageView.contentMode = UIViewContentMode.ScaleAspectFit
        imageView.image = UIImage(named: name)
        imageView.backgroundColor = UIColor.redColor()
        cell.addSubview(imageView)

        return cell
    }
}

EDIT: I was able to crop off the empty space at the bottom of the UICollectionView by creating an outlet for the height constraint ( control + drag height constraint in interface builder onto viewController swift file) calling it heightConstraint, and then at the bottom of viewDidAppear added these two lines of code:

self.heightConstraint.constant = collectionView.contentSize.height
self.view.layoutIfNeeded()

So to show you the result with a white background on the UICollectionView and a red background on the UIImageViews, here is the result (also works on all other device sizes):

enter image description here

BeniaminoBaggins
  • 11,202
  • 41
  • 152
  • 287