UICollectionView cells not horizontal after rotati

2020-03-30 07:36发布

问题:

I have a UICollectionView with a button to create cells, which should appear in the order of creation (1,2,3,4 across and down as space permits). The text views are constrained with flexible widths to fill the cell. The size of the cell depends on the device and rotation to allow 1, 2, 3 or 4 cells per row as follows:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
{
    var size = collectionView.bounds.size       // size of collection view

    switch size.width
    {
    case 0...450:
        println(size.width)
        return CGSize(width: (size.width - 10), height: 145)
    case 451..<768:
        println(size.width)
        return CGSize(width: ((size.width - 10) / 2), height: 145)
    case 768:
        println(size.width)
        return CGSize(width: ((size.width - 10) / 3), height: 145)
    default:
        println(size.width)
        return CGSize(width: 248, height: 150)      // in case there is no size
    }
}

With left and right insets set to 0, this sort of works - but only if I rotate the device and add a cell. In detail:

  1. Simulating an iPhone 5, if cells are added in portrait they appear below each other, as intended, but when the device is rotated, the cells remain in a vertical column instead of two cells per row. If I add a cell while in landscape, the cells then arrange themselves two cells per row, which is correct (except for having to add a cell to make it happen).
  2. Simulating an iPad, if cells are added in portrait, instead of three, only two cells are added per row with space for a third cell between them.
  3. Continuing on iPad, if the device is rotated, instead of four, only three cells appear in each row with space between them. Similar to the iPhone, if another cell is added while in landscape mode, four cells appear per row as expected, AND if the device is rotated back to portrait, three cells are positioned per row, which is correct (except for having to rotate the device, add a cell and rotate it back).

I am calling reloadData when adding the cells, and if I understand correctly, I should not have to call reload upon device rotation (called automatically). Why do I have to rotate the device to landscape and add a cell for the correct layouts to appear in both orientations?

As requested, here is a thinned out version of the source code for the VC. With a simple cell (244*150 with text field 228) and button in the footer, this should repeat the problem:

import UIKit

class CountCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout
{
private var reuseIdentifier = "CountCell"

var cells = 1

override func viewDidLoad() {
    super.viewDidLoad()
    self.collectionView!.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
}

@IBAction func addCount(sender: AnyObject)
{
    cells += 1
    self.collectionView?.reloadData()
}

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

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

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 
{
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as UICollectionViewCell
    return cell
}

override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView
{
    switch kind     // the kind of supplimentary view provided by layout
    {
    case UICollectionElementKindSectionFooter:      // section header was selected in storyboard
        let footerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "CountFooterView", forIndexPath: indexPath) as UICollectionReusableView     // deque and select correct header
        return footerView

    default:
        assert(false, "Unexpected element kind")
    }
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
{
    var size = collectionView.bounds.size
    switch size.width
    {
    case 0...450:
        return CGSize(width: (size.width - 20), height: 145)
    case 451..<768:
        return CGSize(width: ((size.width - 20) / 2), height: 145)
    case 768:
        return CGSize(width: ((size.width - 20) / 3), height: 145)
    default:
        return CGSize(width: 248, height: 150)
    }
}

private let sectionInsets = UIEdgeInsets(top: 20.0, left: 0, bottom: 50.0, right: 0.0)

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAtIndex section: Int) -> UIEdgeInsets
{
    return sectionInsets
}

}

回答1:

Number 33 = items count! You can tweak it independently from your total items count to fit more or less items in screen! For example / (Double(33)) on iPhone 4 will fit 33 items in 4 columns and 4 items per row! in iPhone 6 Plus you will see same picture cells will scale up respecting 4 columns!

// ...........returning cell size based on device screen size by calculating square roo

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

            let deviceSize = UIScreen.mainScreen().bounds.size
            let cellSize = sqrt(Double(deviceSize.width * deviceSize.height) / (Double(33)))

                return CGSize(width: cellSize , height: cellSize)

        }


回答2:

Are you setting the no of sections as 1, If not set it as 1 and try again.