简体   繁体   中英

Different cell sizes with an collectionView based on constraints

I've created a collectionView where i have 3 cells the first cells has to fill first row and the third should fill second row however i can't seem to figure out how to do this, since everytime i try to do in sizeForItemAt i get that the collectionView frame is (0, 0, 0, 0) .

Here is what i have at the moment

class FlowLayout: UICollectionViewFlowLayout {

    var numberOfCells: Int!

    override init() {
        super.init()
        setupLayout()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupLayout()
    }

    func setupLayout() {
        minimumInteritemSpacing = 1
        minimumLineSpacing = 1

    }

    override var itemSize: CGSize {
        set {

        }
        get {
            let numberOfColumns: CGFloat = 2

            let itemWidth = (self.collectionView!.frame.width - (numberOfColumns - 1)) / numberOfColumns
            let itemHeight = self.collectionView!.frame.height / 2


            return CGSize(width: itemWidth, height: itemHeight)
        }
    }


}

illustration of what i want

setting up collectionView in my view

func createCollectionView() {
    let layout = FlowLayout()
    layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    layout.numberOfCells = 2



    collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
    collectionView.dataSource = self
    collectionView.delegate = self
    collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
    collectionView.backgroundColor = UIColor.white
    collectionView.isScrollEnabled = false
    self.topWrapperView.addSubview(collectionView)


    collectionView.snp.makeConstraints { (make) -> Void in

        make.left.equalTo(topWrapperView).offset(0)
        make.top.equalTo(topWrapperView).offset(0)
        make.bottom.equalTo(topWrapperView).offset(0)
        make.right.equalTo(topWrapperView).offset(0)
    }
}

在此处输入图片说明

I had a similar situation except it was the first cell that I wanted 2 cells in first row, with 3 each row after. Used it for a main profile pic and bio in a collection view of images. I successfully implemented it using sizeForItemAtIndexPath with default UICollectionViewDelegateFlowLayout. Here is something that should work for your situation:

 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

let insets = collectionView.contentInset
let collectionViewWidth = collectionView.frame.width - (insets.left + insets.right + 1)
let collectionViewHeight = collectionView.frame.height - (insets.top + insets.bottom)

  switch indexPath.row {
   case 0, 1:

   return CGSize(width: collectionViewWidth / 2, height: collectionViewHeight / 2)

    default:
    return CGSize(width: collectionViewWidth, height: collectionViewHeight / 2)
  }
}

You can change what you divide height by to get desired height.

This is what I wrote for my situation, figured I'd post it incase it can help you or anyone else who reads it. If you want it to change with rotation, use viewWillTransition and set a bool flag with a didSet listener:

 var isPortraitOrientation: Bool = true {
   didSet {
 if oldValue != isPortraitOrientation {
    collectionView?.collectionViewLayout.invalidateLayout()
     }
   }
} 

 override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
   super.viewWillTransition(to: size, with: coordinator)
  isPortraitOrientation = (size.width - size.height) <= 0 ? true : false
}


 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    let insets = collectionView.contentInset
    let collectionViewWidth = collectionView.frame.width - (insets.left + insets.right + 1)
    let collectionViewHeight = collectionView.frame.height - (insets.top + insets.bottom)

    switch indexPath.row {
    case 0:

        if textViewSelected {
            return isPortraitOrientation ? CGSize(width: collectionViewWidth, height: collectionViewHeight / 2) : CGSize(width: collectionViewWidth, height: collectionViewWidth / 3)
        } else {
            return isPortraitOrientation ? CGSize(width: collectionViewWidth / 2, height: collectionViewWidth / 2) : CGSize(width: collectionViewWidth / 2, height: collectionViewHeight / 1.5)
        }
    case 1:
        return isPortraitOrientation ? CGSize(width: collectionViewWidth / 2, height: collectionViewWidth / 2) : CGSize(width: collectionViewWidth / 2, height: collectionViewHeight / 1.5)

    default:
        return isPortraitOrientation ? CGSize(width: collectionViewWidth / 3, height: collectionViewWidth / 3) : CGSize(width: collectionViewWidth / 5, height: collectionViewWidth / 5)
    }
}

EDIT:

based on your additional code, instead of doing CGRect.zero for the collectionView frame use topWrapperView.bounds.

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