简体   繁体   English

基于约束的collectionView具有不同的像元大小

[英]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) . 我创建了一个collectionView,其中我有3个单元格,第一个单元格必须填充第一行,第三个单元格应该填充第二行,但是由于每次我尝试在sizeForItemAt进行操作,我似乎都无法弄清楚sizeForItemAt collectionView框架为(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 在我的视图中设置collectionView

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. 我有一个类似的情况,只是它是第一个单元格,所以我希望在第一行中有2个单元格,之后每行3个。 Used it for a main profile pic and bio in a collection view of images. 用于图像的集合视图中的主要个人资料图片和个人简介。 I successfully implemented it using sizeForItemAtIndexPath with default UICollectionViewDelegateFlowLayout. 我使用具有默认UICollectionViewDelegateFlowLayout的sizeForItemAtIndexPath成功实现了它。 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: 如果您希望它随旋转而变化,请使用viewWillTransition并使用didSet侦听器设置一个bool标志:

 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. 根据您的其他代码,而不是对collectionView框架执行CGRect.zero,请使用topWrapperView.bounds。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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