4

I'm trying to make a Photo Gallery using UICollectionView with Swift. I want to display photos in full screen and swipe right to get to the next image. I have a working code for the portrait frame but as soon as I go to landscape it seems like my cell doesn't re-adjust itself to the correct position and size.

Meaning that it keeps the same width,height, x position and y position of the portrait screen at all times. I also get this error on both portrait and landscape frame:

->the behavior of the UICollectionViewFlowLayout is not defined because:

->the item height must be less that the height of the UICollectionView minus the section insets top and bottom values.

I have looked all over the web for an answer and have tried all possible solutions but it doesn't seem to be working for me. Let me know if anyone can help out with this. Much appreciated.

Here is my code :

import UIKit

class ImageDetailViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout,UINavigationControllerDelegate {


@IBOutlet weak var imgDetailCollectionView: UICollectionView!

var index: Int!
var imageItems: Array<Items> = []
var currentIndex: CGFloat!
var size = UIScreen.mainScreen().bounds.size
init(index: Int , imageItems: Array<Items>) {
    self.index = index
    self.imageItems = imageItems
    super.init(nibName: "ImageDetailViewController", bundle: NSBundle.mainBundle())
}

required init(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
    super.viewDidLoad()


    imgDetailCollectionView.registerNib(UINib(nibName: "ImageDetailCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "ImageDetailCollectionViewCell")
    //self.automaticallyAdjustsScrollViewInsets = false
    imgDetailCollectionView.setZoomScale(0.5, animated: true)

}




override func viewDidLayoutSubviews() {
    imgDetailCollectionView.scrollRectToVisible(CGRectMake(320 * CGFloat(index), 0, 320 , 240), animated: false)
}



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

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

    return self.imageItems.count
}


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






    var cell = imgDetailCollectionView.dequeueReusableCellWithReuseIdentifier("ImageDetailCollectionViewCell", forIndexPath: indexPath) as ImageDetailCollectionViewCell

    cell.setup(imageItems[indexPath.row].url!)

    if(UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation)){


        self.imgDetailCollectionView.collectionViewLayout.invalidateLayout()

        var frame = cell.frame
        frame.size = CGSizeMake(size.width, size.height)
        cell.frame = frame

    }else{
        self.imgDetailCollectionView.collectionViewLayout.invalidateLayout()

        var frame = cell.frame
        frame.size = CGSizeMake(size.height, size.width)
        cell.frame = frame
    }

    return cell

}


func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

    var size = UIScreen.mainScreen().bounds.size

    if(UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation)){


        return CGSizeMake(size.width, size.height)


    }else{

        return CGSizeMake(size.height, size.width)
    }



}

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

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


override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
    self.imgDetailCollectionView.collectionViewLayout.invalidateLayout()

    var currentOffset = self.imgDetailCollectionView.contentOffset
    self.currentIndex = currentOffset.x / imgDetailCollectionView.frame.size.width

}


override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {

    var currentSize = imgDetailCollectionView.bounds.size
    var offset = self.currentIndex * currentSize.width
    imgDetailCollectionView.setContentOffset(CGPointMake(offset, 0), animated: false)

    imgDetailCollectionView.reloadData()
}

override func willAnimateRotationToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {

    self.imgDetailCollectionView.collectionViewLayout.invalidateLayout()
}
}
Bhumika
  • 866
  • 7
  • 20
Amir H
  • 43
  • 1
  • 6

2 Answers2

1

Your problem is you are checking the orientation and using the height for the width when it is in landscape mode. This is incorrect. When the device is rotated, the width property will return the actual height of the device when it was in portrait.

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    var cell = imgDetailCollectionView.dequeueReusableCellWithReuseIdentifier("ImageDetailCollectionViewCell", forIndexPath: indexPath) as ImageDetailCollectionViewCell
    cell.setup(imageItems[indexPath.row].url!)
    cell.frame.size = view.frame.size
    return cell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSizeMake(view.frame.width, view.frame.height)
}

Also another note, apple recommends that you use the viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) method because this is the newer API. Also, in iOS9 if you use this method instead you will be enabling the multitasking feature by using this method.

Manav Gabhawala
  • 947
  • 9
  • 10
1

This error might be printed because of next line:

var size = UIScreen.mainScreen().bounds.size

For fast check you can type for example:

var size = UIScreen.mainScreen().bounds.size * 0.25

If error message dissapear, you should follow instructions from message and subtract collectionView's contentInsets and sectionInsets from available height (collectionView.bounds.height).

Doing so, you will avoid situation in which cell height is trying to be 'higher' than it's collectionView.