简体   繁体   中英

Landscape orientation for Collection View in Swift

I am encountering a problem on landscape orientation for my collection view cell. When the app is in portrait it gives me the correct number of cell per row which is 2. But when I rotate my app to landscape it display 1 cell per row. Here's the screen of what I got:

Portrait: 在此处输入图片说明

Landscape: 在此处输入图片说明

Here's my code for adding the size of the cell:

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

        var screenSize = CGFloat()
        if UIDevice.currentDevice().orientation.isLandscape.boolValue {
            screenSize = UIScreen.mainScreen().bounds.size.width
        }
        else {
            screenSize = UIScreen.mainScreen().bounds.size.width
        }

        let cellWidth = screenSize / 2.0

        return CGSizeMake(cellWidth, cellWidth)
    }

Here is what you can do

let orientation = UIApplication.sharedApplication().statusBarOrientation
if(orientation == .LandscapeLeft || orientation == .LandscapeRight)
{
    return CGSizeMake((yourCollectionView.frame.size.width-10)/2, (yourCollectionView.frame.size.height-10)/2)
}
else{
    return CGSizeMake((yourCollectionView.frame.size.width-5)/2, (yourCollectionView.frame.size.height-10)/3)
}

What this code achieves:- If your view is in portrait you will see 2 column and 3 row and if your view is in landscape you will see 3 columns and 2 row. The deduction you see in the code is the spacing between two consecutive cells. So if there is 3 column the deduction is 15 and if there is 2 column the deduction is 10 assuming that the spacing between two cell is 5. Same goes for the row.

You can use the screen size as well if you want but I had auto layout constraints in my collection view to match the size of the screen so it resulted the same. I hope this is what you were looking for.

Just reload your UICollectionView in

override

func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)

        yourCollectionView.reloadData()
    }

and your collection view layout will refresh again when orientation changed

Update: This is code snippet for collectionView layout making 4 image view in each row from my code, and its working even it changing orientation from portrait to landscape and vice versa. You can change it to your need:

func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: UIScreen.main.bounds.width / 4.8, height: UIScreen.main.bounds.width / 4.8)
}

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

    return UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0)
}

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

    return 0.0
}

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

    return 16.0
}

Hope it will helps you.

Cheers!

Swift 5

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    var flag:CGSize? = nil
    if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad
    {
        if UIApplication.shared.statusBarOrientation.isPortrait{

            let cellWidth = floor((collectionView.bounds.width - 5) / 2)
            flag = CGSize(width: cellWidth, height: cellWidth)
        }

        else if UIApplication.shared.statusBarOrientation.isLandscape{

            let cellwidth = floor((collectionView.bounds.width - 5) / 4)
            flag =  CGSize(width: cellwidth, height: cellwidth)

        }

    }
    else if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.phone{

        if UIApplication.shared.statusBarOrientation.isLandscape {
          let cellWidth = floor((collectionView.bounds.width - 5) / 2)
            flag = CGSize(width: cellWidth, height: cellWidth)
        } else if UIApplication.shared.statusBarOrientation.isPortrait{
            //  let cellWidth = floor((collectionView.bounds.width - 5))
            flag = CGSize(width: 402 , height: 185)
        }

    }

    return flag!
}

Swift 4.2

let orientation = UIApplication.shared.statusBarOrientation
    if(orientation == .landscapeLeft || orientation == .landscapeRight) {
        return CGSize(width: (collectionView.frame.size.width-10)/2, height: (collectionView.frame.size.height-10)/2)
    }
    else {
        return CGSize(width: (collectionView.frame.size.width-5)/2, height: (collectionView.frame.size.height-10)/3)
    }

don't reload your collection view just invalidate your collection view flowlayour Done

if you don't understand what is that means just copy and paste this code and change your collection view name

override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews()

fiveCellCustomCollectionView is my custom view and customCollectionView is collection view

  guard let flowLayout = fiveCellCustomCollectionView.customCollectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return }
  flowLayout.invalidateLayout()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM