プログラムでUICollectionViewCellの幅と高さを設定する方法


103

を実装しようとしていCollectionViewます。自動レイアウトを使用している場合、セルのサイズは変更されませんが、配置は変更されます。

今私はむしろそれらのサイズを例えばに変更したいと思います

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

で設定してみました CellForItemAtIndexPath

collectionCell.size = size

それはうまくいきませんでした。

これを達成する方法はありますか?

編集

答えは私のCollectionViewの幅と高さ自体を変更するだけのようです。制約に矛盾はありますか?その上で何かアイデアはありますか?

回答:


267

このメソッドを使用して、カスタムセルの高さの幅を設定します。

このプロトコルを必ず追加してください

UICollectionViewDelegate

UICollectionViewDataSource

UICollectionViewDelegateFlowLayout

あなたが使用している場合は迅速5またはXcodeの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)
    }
}

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

1
@RamyAlZuhouri編集した回答を確認して、さらに明確にする必要があるかどうか確認してください
PinkeshGjr

8
私はすべてをプログラムで行うことに慣れているので、これは今では私にとって非常に異質なようです。StoryboardでEstimated SizeNoneに設定し、UICollectionViewDelegateFlowLayoutを追加することがトリックです
Lance Samaria

5
Estimate Sizeをnoneに設定するとうまくいきました。ありがとう@PinkeshGjr
Mohan

5
私はこれを見つけてうれしいです。魔法の「サイズを推定しない」を学ぶためだけにこれを追いかけて2時間無駄にしました
Klajd Deda

3
Estimate Sizeをnoneに設定して、私の日を節約しました。
tounaobun

73

宣言にプロトコルを必ず追加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)
    }
}

カスタムではなくフローレイアウトを使用することを忘れないでください。次に、私のために働いたのはあなただけです。ありがとう!
Sean

動的高さをここでどのようにして静的高さを100.0として与えることができますか
サンガビ

65

ストーリーボードを使用してUICollectionViewDelegateFlowLayoutをオーバーライドしている場合、Swift 5とXcode 11でもEstimate sizeをNoneに設定します ここに画像の説明を入力してください


2
それは役に立ちました。ありがとう!!
海軍ハサン

それは間違いなく私が夢中になろうとしていたことでした。noneに設定しない限り、sizeForItemメソッドで指定した正しいサイズを確認できません。
Yusuf Kamil AK

2
見積もりサイズをnoneに設定すると、すべてが修正されます
MMK

2
Thnx設定の見積もりサイズを問題なしで修正なし
Salman500

2
良い修正。ここによると、この問題の私の診断だAppleのドキュメントにはUICollectionViewFlowLayoutデフォルトに思えるestimatedItemSizeUICollectionViewFlowLayout.automaticSizeドキュメントはそれがデフォルトで設定される必要があり言うにもかかわらず、IBを使用した場合CGSizeZero。Appleが述べているように、automaticSize「コレクションビューでセルのセルフサイズ設定を有効にします」。これが、IBの他のサイズ変更が何もしない理由です。
Andrew Kirna

20

ようやく答えが出ました。UICollectionViewDelegateFlowLayout
これを拡張する必要がありますこれは上記の回答で動作するはずです。


例を書いていただけませんか?
Mamdouh El Nakeeb 2017年

実際、私はdatasourceとdelegateFlowLayoutプロトコルの両方で拡張を行いましたが、機能しませんでした。機能したのは、FlowLayoutパーツを独自の拡張に分離することでした。理由は定かではありませんが、Swift 3で機能しました
Skywalker

15

迅速な4.1

CollectionViewのサイズを変更するには、2つの方法があります。
最初の方法 ->このプロトコルUICollectionViewDelegateFlowLayout
を追加します。私の場合、セルを1行で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
    }
}

2番目の方法 -> 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番目の方法のどちらでコードを記述しても、上記と同じ結果が得られます。私はそれを書きました。 それは私のために働いた

ここに画像の説明を入力してください


2
ストレートraywenderlich.com😂から
アンドリューKirna

12

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制約も無効にする必要があります。


これと上記のすべての解決策を試しましたが、セルの内容が自動サイズ変更されません。これを修正するにはどうすればよいですか
Biasi Wiga

7

コレクションビューにはレイアウトオブジェクトがあります。あなたの場合、それはおそらくフローレイアウトUICollectionViewFlowLayout)です。フローレイアウトのitemSizeプロパティを設定します。


これを試しました。以前と同じ問題を私に与えます。どういうわけか、私のCollectionViewは、セルではなくサイズを変更します。
JVS 2016年

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 swift 4 iosコレクションビューコレクションビューの例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)
}

/////サンプルの完全なコード

ストーリーボードのコレクションビューとコレクションビューのセルで作成すると、コレクションを
@IBOutlet として参照できます。弱い変数cvContent:UICollectionView!

これをビューコントローラに貼り付けます

 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

もう1つの方法は、フローレイアウトで値を直接設定することです

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

0

したがって、セルセクションのcollectionViewの属性のストーリーボードからSizeを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」という基本クラスがあることに注意してください。イニシャライザの「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あなたのプロジェクトにおそらくあるでしょう(初期化子のための追加のIに注意してください!)。


0

Swift 5、Programmatic 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); 
} 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.