如何以编程方式设置UICollectionViewCell的宽度和高度


100

我正在尝试实施一个CollectionView。当我使用“自动布局”时,单元格不会更改大小,而是对齐。

现在我想将其大小更改为

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

我尝试设置 CellForItemAtIndexPath

collectionCell.size = size

虽然没有用。

有没有办法做到这一点?

编辑

看来,答案只会改变我的CollectionView宽度和高度本身。约束中可能存在冲突吗?有什么想法吗?

Answers:


256

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

确保添加此协议

UICollectionViewDelegate

UICollectionViewDataSource

UICollectionViewDelegateFlowLayout

如果您使用的是swift 5xcode 11及更高版本,则需要设置Estimate Sizenone使用情节提要以使其正常运行。如果您未设置,则下面的代码将无法正常工作。

在此处输入图片说明

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)
    }
}

物镜

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

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

1
@RamyAlZuhouri编辑了我的答案,请检查并告知我们是否仍然需要使它更清晰
PinkeshGjr

8
我已经习惯于以编程方式完成所有事情,以至于现在这对我来说似乎太陌生了。在情节提要中,将“ 估计大小”设置为“ 无”并添加UICollectionViewDelegateFlowLayout是有效的方法
Lance Samaria

5
将“估计大小”设置为“无”对我来说无效。谢谢@PinkeshGjr
Mohan

5
我很高兴自己找到了这个,我浪费了2个小时来追逐它,只是为了学习神奇的“估计大小为无”
Klajd Deda

3
将[估算大小]设为[无,可节省我的日子]。
tounaobun

73

确保UICollectionViewDelegateFlowLayoutclass声明中添加协议

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)
    }
}

不要忘记使用流布局而不是自定义。那么,您的人是唯一为我工作的人。谢谢!
肖恩

我们如何在此处给出动态高度,在此处给出静态高度为100.0
sangavi

62

如果使用故事板并覆盖UICollectionViewDelegateFlowLayout,则在swift 5和Xcode 11中还将“ 估计大小”设置为“无”。 在此处输入图片说明


1
那很有帮助。谢谢!!
海军哈桑

那绝对是我要疯的样子。除非将其设置为none,否则您将看不到sizeForItem方法中给定的正确大小。
优素福·卡米尔

1
将估算大小设置为无固定值
MMK

1
Thnx将估计大小设置为无问题固定
Salman500

2
好解决。这里是我根据这个问题的诊断苹果的文档UICollectionViewFlowLayout似乎默认estimatedItemSizeUICollectionViewFlowLayout.automaticSize即使文件说,它应该默认使用IB时CGSizeZero。如Apple所述,automaticSize“为您的收藏夹视图启用自动调整大小的单元格”。这就是为什么IB中其他大小的更改无济于事的原因。
Andrew Kirna

20

终于得到了答案。您应该扩展UICollectionViewDelegateFlowLayout
这应该与上面的答案一起使用。


你能写一个例子吗?
Mamdouh El Nakeeb '17

实际上,我对数据源和委托流布局协议都进行了扩展,但是没有用。起作用的是将FlowLayout部分分离为其自身的扩展。不知道为什么,但是很快就起作用了。–
天行者

15

迅捷4.1

您有2种方法可以更改CollectionView的大小。
第一种方法 ->添加此协议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
    }
}

第二种方法 ->您不必添加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
    }
}

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

在此处输入图片说明


2
直接从raywenderlich.com😂
安德鲁Kirna

11

根据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)
}

也许您还应该在单元格上禁用自动布局约束,以使此答案生效。


我尝试了上述所有解决方案,但单元格中的内容未自动调整大小,我该如何解决
Biasi Wiga

7

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


试过这个。给我像以前一样的问题。我的CollectionView会以某种方式更改其大小,而不是更改单元格。
JVS

2
好吧,这取决于您何时进行操作。您尚未显示真实代码,那么谁知道您在做什么呢?我向您保证它确实有效。
马特

7

Swift3Swift4中,您可以通过添加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)

4

swift4 swift4 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

class 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
    }
}

2

请尝试以下方法

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

2

Swift 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)
    }()

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.

1

2020年,绝对简单的方法:

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource {

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

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource,
     UICollectionViewDelegateFlowLayout {

键入“ 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)

0

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

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

0

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


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)
}

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”。初始化程序的“我”。

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

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

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(请注意额外的I for Initializer!)。


0

Swift 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)
        ])
    }
    
}

-4

这是我的版本,根据您的要求找到适合的比例以获得像元大小。

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath 
{ 
return CGSizeMake(CGRectGetWidth(collectionView.frame)/4, CGRectGetHeight(collectionView.frame)/4); 
} 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.