如何以编程方式设置UICollectionViewCell Width和Height

时间:2016-06-25 11:30:50

标签: swift uicollectionview

我正在尝试实施CollectionView。 当我使用Autolayout时,我的细胞不会改变大小,而是它们的对齐。

现在我宁愿将他们的尺寸改为例如。

//var size = CGSize(width: self.view.frame.width/10, height: self.view.frame.width/10)

我尝试在我的CellForItemAtIndexPath

中进行设置
collectionCell.size = size
但它没有工作。

有没有办法实现这个目标?

修改

似乎答案只会改变我的CollectionView宽度和高度本身。约束中是否存在冲突?有什么想法?

21 个答案:

答案 0 :(得分:94)

使用此方法设置自定义单元格高度宽度。

确保添加此协议

UICollectionViewDelegate

UICollectionViewDataSource

UICollectionViewDelegateFlowLayout
  

<强>目标C

@interface YourViewController : UIViewController<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake(CGRectGetWidth(collectionView.frame), (CGRectGetHeight(collectionView.frame)));
}
  

Swift 4或更高版本

extension YourViewController: UICollectionViewDelegate {
    //Write Delegate Code Here
}

extension YourViewController: UICollectionViewDataSource {
    //Write DataSource Code Here
}

extension YourViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: screenWidth, height: screenWidth)
    }
}

答案 1 :(得分:57)

确保在UICollectionViewDelegateFlowLayout声明

中添加协议class
class MyCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout
{
    //MARK: - UICollectionViewDelegateFlowLayout

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
    {
       return CGSize(width: 100.0, height: 100.0)
    }
}

答案 2 :(得分:19)

如果使用故事板并覆盖 UICollectionViewDelegateFlowLayout ,则在Swift 5和Xcode 11中还将估算尺寸设置为“无” enter image description here

答案 3 :(得分:18)

终于得到了答案。 你应该延长UICollectionViewDelegateFlowLayout
这应该与上面的答案一起使用。

答案 4 :(得分:10)

  

swift 4.1

您有两种方法可以更改CollectionView的大小 第一种方式 - &gt;添加此协议 UICollectionViewDelegateFlowLayout
在我的情况下,我想将细胞分成一行中的3个部分。我在下面做了这段代码

extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource ,UICollectionViewDelegateFlowLayout{
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
    {
            // In this function is the code you must implement to your code project if you want to change size of Collection view
            let width  = (view.frame.width-20)/3
            return CGSize(width: width, height: width)
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return collectionData.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath)
        if let label = cell.viewWithTag(100) as? UILabel {
            label.text = collectionData[indexPath.row]
        }
        return cell
    }
}

第二种方式 - &gt;您必须添加 UICollectionViewDelegateFlowLayout ,但您必须在 viewDidload函数中编写一些代码,而不是下面的代码

class ViewController: UIViewController {
@IBOutlet weak var collectionView1: UICollectionView!
        var collectionData = ["1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9.", "10.", "11.", "12."]

    override func viewDidLoad() {
        super.viewDidLoad()
        let width = (view.frame.width-20)/3
        let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
        layout.itemSize = CGSize(width: width, height: width) 
    }
}


extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {


    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return collectionData.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath)
        if let label = cell.viewWithTag(100) as? UILabel {
            label.text = collectionData[indexPath.row]
        }

        return cell
    }
}

无论您编写代码作为第一种方式还是第二种方式,您都将得到与上述相同的结果。我写的。 对我有用

enter image description here

答案 5 :(得分:8)

尺寸比例根据iPhone尺寸:

以下是关于iPhone尺寸的单元格宽度和高度的不同之处:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    let width = (self.view.frame.size.width - 12 * 3) / 3 //some width
    let height = width * 1.5 //ratio
    return CGSize(width: width, height: height)
}

也许您还应该禁用对单元格的AutoLayout约束,以使此答案起作用。

答案 6 :(得分:6)

集合视图有一个布局对象。在您的情况下,它可能是流程布局UICollectionViewFlowLayout)。设置流布局的itemSize属性。

答案 7 :(得分:4)

Swift3 Swift4 中,您可以通过添加 UICollectionViewDelegateFlowLayout 并实现以下方式来更改单元格大小:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 100, height: 100)
    }

或者如果以编程方式创建UICollectionView,您可以这样做:

    let layout = UICollectionViewFlowLayout()
                    layout.scrollDirection = .horizontal //this is for direction
                    layout.minimumInteritemSpacing = 0 // this is for spacing between cells
                    layout.itemSize = CGSize(width: view.frame.width, height: view.frame.height) //this is for cell size
let collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout)

答案 8 :(得分:3)

swift4 swift 4 ios集合视图collectionview示例xcode最新代码工作示例

在顶部的“委托”部分添加

UICollectionViewDelegateFlowLayout

并使用此功能

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = (self.view.frame.size.width - 20) / 3 //some width
    let height = width * 1.5 //ratio
    return CGSize(width: width, height: height)
}

////// 示例完整代码

在情节提要中的集合视图上创建集合和collectionview单元对集合进行引用为
  @IBOutlet弱var cvContent:UICollectionView!

将此内容粘贴到View控制器

import UIKit

ViewController类:UIViewController,UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {

var arrVeg = [String]()
var arrFruits = [String]()
var arrCurrent = [String]()

@IBOutlet weak var cvContent: UICollectionView!



override func viewDidLoad() {
    super.viewDidLoad()
    arrVeg = ["Carrot","Potato", "Tomato","Carrot","Potato", "Tomato","Carrot","Potato", "Tomato","Carrot","Potato", "Tomato"]

    arrVeg = ["Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange","Mango","Papaya","Orange"]


    arrCurrent = arrVeg
}
//MARK: - CollectionView



func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = (self.view.frame.size.width - 20) / 3 //some width
    let height = width * 1.5 //ratio
    return CGSize(width: width, height: height)
}

func numberOfSections(in collectionView: UICollectionView) -> Int {

    return 1
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {


    return arrCurrent.count
}



func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! ContentCollectionViewCell
    cell.backgroundColor =  UIColor.green
    return cell
}

}

答案 9 :(得分:2)

尝试以下方法

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    return CGSize(width: 100.0, height: 100.0)
}

答案 10 :(得分:1)

**Swift 5**
To make this work you have to do the following.

Add these protocols

 - UICollectionViewDelegate


 - UICollectionViewDataSource


 - UICollectionViewDelegateFlowLayout

Your code will then look like this

extension YourViewController: UICollectionViewDelegate {
    //Write Delegate Code Here
}

extension YourViewController: UICollectionViewDataSource {
    //Write DataSource Code Here
}

extension YourViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: screenWidth, height: screenWidth)
    }
}

Now the final and crucial step to see this take effect is to go to your viedDidLoad function inside your Viewcontroller.

    override func viewDidLoad() {
        super.viewDidLoad()
        collection.dataSource = self // Add this
        collection.delegate = self // Add this

        // Do any additional setup after loading the view.
    }

Without telling your view which class the delegate is it won't work.

答案 11 :(得分:1)

#绝对简单的方法:

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource {

#您必须添加“ UICollectionViewDelegateFlowLayout”,否则就不会自动完成:

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource,
     UICollectionViewDelegateFlowLayout {

#Type“ sizeForItemAt ...”。大功告成!

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource,
     UICollectionViewDelegateFlowLayout {
 
     func collectionView(_ collectionView: UICollectionView,
      layout collectionViewLayout: UICollectionViewLayout,
      sizeForItemAt indexPath: IndexPath) -> CGSize {
     
     return CGSize(width: 37, height: 63)
}

就是这样。

例如,如果要“每个单元格填充整个集合视图”:

     guard let b = view.superview?.bounds else { .. }
     return CGSize(width: b.width, height: b.height)

答案 12 :(得分:0)

另一种方法是直接在流程布局中设置值

    let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
    layout.itemSize = CGSize(width: size, height: size)

答案 13 :(得分:0)

以编程方式快速5

lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal

        //Provide Width and Height According to your need
        let cellWidth = UIScreen.main.bounds.width / 10
        let cellHeight = UIScreen.main.bounds.height / 10
        layout.itemSize = CGSize(width: cellWidth, height: cellHeight)

        //You can also provide estimated Height and Width
        layout.estimatedItemSize = CGSize(width: cellWidth, height: cellHeight)

        //For Setting the Spacing between cells
        layout.minimumInteritemSpacing = 0
        layout.minimumLineSpacing = 0

        return UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
    }()

答案 14 :(得分:0)

一种简单的方法:

如果您只需要简单的固定大小

class SizedCollectionView: UIICollectionView {
    override func common() {
        super.common()
        let l = UICollectionViewFlowLayout()
        l.itemSize = CGSize(width: 42, height: 42)
        collectionViewLayout = l
    }
}

仅此而已。

在情节提要中,只需将类从UICollectionView更改为SizedCollectionView。

但是!!!

请注意,基类存在“ UI'I'CollectionView”。 “ I”代表初始化器。

向集合视图添加初始化器并不容易。这是一种常见的方法:

集合视图...带有初始化程序:

import UIKit

class UIICollectionView: UICollectionView {
    private var commoned: Bool = false
    
    override func didMoveToWindow() {
        super.didMoveToWindow()
        if window != nil && !commoned {
            commoned = true
            common()
        }
    }
    
    internal func common() {
    }
}

在大多数项目中,您需要“带有初始化程序的集合视图”。因此,无论如何,您的项目中可能都会有UIICollectionView(请注意要为Initializer附加的I!)。

答案 15 :(得分:0)

因此,您需要从情节提要中将单元格区域估计大小中collectionView的属性设置为无,并且在ViewController中,您需要具有用于实现此方法的委托方法:optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize

答案 16 :(得分:0)

尝试使用UICollectionViewDelegateFlowLayout方法。在Xcode 11或更高版本中,您需要将情节提要中的“估计大小”设置为“无”。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: 
UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let padding: CGFloat =  170
    let collectionViewSize = advertCollectionView.frame.size.width - padding
    return CGSize(width: collectionViewSize/2, height: collectionViewSize/2)
}

答案 17 :(得分:0)

快速5,程序化UICollectionView设置单元格的宽度和高度

// MARK: MyViewController

final class MyViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
    private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
        let layout = UICollectionViewFlowLayout()
        let spacing: CGFloat = 1
        let numOfColumns: CGFloat = 3
        let itemSize: CGFloat = (UIScreen.main.bounds.width - (numOfColumns - spacing) - 2) / 3
        layout.itemSize = CGSize(width: itemSize, height: itemSize)
        layout.minimumInteritemSpacing = spacing
        layout.minimumLineSpacing = spacing
        layout.sectionInset = UIEdgeInsets(top: spacing, left: spacing, bottom: spacing, right: spacing)
        return layout
    }()
    
    private lazy var collectionView: UICollectionView = {
        let collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: collectionViewLayout)
        collectionView.backgroundColor = .white
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.translatesAutoresizingMaskIntoConstraints = false
        return collectionView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureCollectionView()
    }
    
    private func configureCollectionView() {
        view.addSubview(collectionView)
        NSLayoutConstraint.activate([
            collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
            collectionView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            collectionView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
        ])
        collectionView.register(PhotoCell.self, forCellWithReuseIdentifier: "PhotoCell")
    }
    
    // MARK: UICollectionViewDataSource

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 20
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCell", for: indexPath) as! PhotoCell
        cell.backgroundColor = .red
        return cell
    }
    
}

// MARK: PhotoCell

final class PhotoCell: UICollectionViewCell {
    
    lazy var imageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.layer.masksToBounds = true
        return imageView
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init?(coder:) not implemented")
    }
    
    func setupViews() {
        addSubview(imageView)
        NSLayoutConstraint.activate([
            topAnchor.constraint(equalTo: topAnchor),
            bottomAnchor.constraint(equalTo: bottomAnchor),
            leadingAnchor.constraint(equalTo: leadingAnchor),
            trailingAnchor.constraint(equalTo: trailingAnchor)
        ])
    }
    
}

答案 18 :(得分:0)

如果像我一样,需要根据集合视图的宽度动态更新自定义流程布局的itemSize,则应覆盖UICollectionViewFlowLayout的{​​{1}}方法。这是WWDC video demoing this technique

prepare()

答案 19 :(得分:0)

如果您没有使用 UICollectionViewController,则需要通过设置委托 UICollectionViewDelegate、UICollectionViewDataSource、UICollectionViewDelegateFlowLayout 来添加一致性。

  extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout

之后,您必须为添加到 ViewController 的集合视图设置一个委托。

  collectionView.delegate = self
  collectionView.dataSource = self


  

最后,您必须向集合视图添加布局:

  let collectionLayout = UICollectionViewFlowLayout()
  collectionView.collectionViewLayout = collectionLayout

完成这些步骤后,您可以在 func 中更改大小:

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

答案 20 :(得分:-3)

这是我的版本,根据您的要求找到合适的比例以获得单元尺寸。

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
return CGSizeMake(CGRectGetWidth(collectionView.frame)/4, CGRectGetHeight(collectionView.frame)/4); 
}