Search code examples
swiftuicollectionviewcell

Unable to give required width, and height for collectionview cell in swift


I have gicen collectionview height as 300 and added cell with imageview and label for label given constraints bottom, leading, trailing = 10 and for image given top, leading, trailing = 10, bottom = 40

enter image description here

code: with this I am getting wired o/p. I can't even see label and too broad imageview. I need 200 height and total screen width. how to fix this issue? how to give proper cell size to show image and label. please guide me.

class CollPagingViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate, UICollectionViewDataSource {

@IBOutlet weak var collectionviewCellSize: UICollectionView!

var cellArray = ["one", "two", "three", "four", "five"]

override func viewDidLoad() {
    super.viewDidLoad()

    collectionviewCellSize.delegate = self
    collectionviewCellSize.dataSource = self
    if let layout = collectionviewCellSize.collectionViewLayout as? UICollectionViewFlowLayout {
            layout.scrollDirection = .horizontal
        }
 }
  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    
    let width = UIScreen.main.bounds.width
    let height = 200.0
    print("cell size:\n width: \(width) heigth: \(height)")
    return CGSize(width: width, height: height)
}

  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return cellArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollCell2", for: indexPath) as! CollCell2
    cell.textLbl.text = cellArray[indexPath.item]
        return cell
}

o/p:

width: 414.0 heigth: 200.0

enter image description here

EDIT: with this code getting correct cellsize but i want using sizeForItemAt method. how? why i am not getting correct cell size using sizeForItemAt?

  override func viewDidLoad() {
    super.viewDidLoad()

    collectionviewCellSize.delegate = self
    collectionviewCellSize.dataSource = self

    let layout = UICollectionViewFlowLayout()
    layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    layout.scrollDirection = .horizontal
    let width = collectionviewCellSize.frame.width
    let height = collectionviewCellSize.frame.height

    layout.minimumInteritemSpacing = 0
    layout.minimumLineSpacing = 0
    layout.itemSize = CGSize(width: width, height: height)
    self.collectionviewCellSize.collectionViewLayout = layout
}

Solution

  • When adding UI elements such as UICollectionView there are a lot of "default" settings that get applied.

    In this case, one notable setting is Estimated Cell Size. If we add a collection view to a view controller, the default is Automatic -- which tells UIKit to use the cell's content to calculate the size... *even if we've implemented sizeForItemAt.

    So, add one line to your flow layout configuration:

        if let layout = collectionviewCellSize.collectionViewLayout as? UICollectionViewFlowLayout {
            layout.scrollDirection = .horizontal
            
            // need this line
            layout.estimatedItemSize = .zero
        }
    

    Now, you should get the proper cell sizing.

    As a side note - you don't want to use UIScreen.main.bounds.width! If the collection view is constrained to the safe area (which is should be), or if the user is running your app in multitasking mode on an iPad, UIScreen.main.bounds.width will not give you what you want.

    Instead, use the collection view's frame:

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        
        // don't use screen!
        //let width = UIScreen.main.bounds.width
        
        // use collection view frame
        let width = collectionView.frame.width
        let height = 200.0
        print("cell size:\n width: \(width) heigth: \(height)")
        return CGSize(width: width, height: height)
    
    }