So legen Sie die Breite und Höhe von UICollectionViewCell programmgesteuert fest

98

Ich versuche ein zu implementieren CollectionView. Wenn ich Autolayout verwende, ändern meine Zellen nicht die Größe, sondern ihre Ausrichtung.

Jetzt möchte ich lieber ihre Größe ändern, z

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

Ich habe versucht, in meinem zu setzen CellForItemAtIndexPath

collectionCell.size = size

es hat aber nicht funktioniert.

Gibt es einen Weg, dies zu erreichen?

bearbeiten :

Es scheint, dass die Antworten nur die Breite und Höhe meiner CollectionView selbst ändern. Sind Konflikte in Constraints möglich? Irgendwelche Ideen dazu?

JVS
quelle

Antworten:

248

Verwenden Sie diese Methode, um die Breite der benutzerdefinierten Zellenhöhe festzulegen.

Stellen Sie sicher, dass Sie diese Protokolle hinzufügen

UICollectionViewDelegate

UICollectionViewDataSource

UICollectionViewDelegateFlowLayout

Wenn Sie mit schnellen 5 oder Xcode 11 und später müssen Sie Satz Estimate Sizezu noneverwenden Storyboard , um es funktioniert einwandfrei . Wenn Sie dies nicht einstellen, funktioniert der folgende Code nicht wie erwartet.

Geben Sie hier die Bildbeschreibung ein

Swift 4 oder höher

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

Ziel 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)));
}
PinkeshGjr
quelle
1
@ RamyAlZuhouri Bearbeitet meine Antwort bitte überprüfen und lassen Sie mich wissen, wenn wir es noch klarer machen müssen
PinkeshGjr
7
Ich bin es so gewohnt, alles programmatisch zu machen, dass mir das jetzt so fremd erscheint. In der Storyboard-Einstellung " Geschätzte Größe auf Keine" und Hinzufügen des UICollectionViewDelegateFlowLayout ist dies der Trick
Lance Samaria
5
Das Setzen der geschätzten Größe auf keine hat bei mir funktioniert. Vielen Dank, dass Sie @PinkeshGjr
Mohan
5
Ich bin froh, dass ich das gefunden habe. Ich habe 2 Stunden damit verbracht, es zu
verfolgen,
3
Wenn Sie die geschätzte Größe auf "Keine" setzen, werden meine Tage gespeichert.
Tunaobun
72

Stellen Sie sicher, dass Sie das Protokoll UICollectionViewDelegateFlowLayoutin Ihrer classDeklaration hinzufügen

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)
    }
}
pierre23
quelle
Vergessen Sie nicht, das Flow-Layout zu verwenden und nicht benutzerdefiniert. Dann ist deine die einzige, die für mich gearbeitet hat. Vielen Dank!
Sean
Wie können wir hier dynamische Höhe geben, indem wir statische Höhe als 100,0
angeben
61

Wenn Sie ein Storyboard verwenden und UICollectionViewDelegateFlowLayout überschreiben, setzen Sie in Swift 5 und Xcode 11 auch die geschätzte Größe auf Keine Geben Sie hier die Bildbeschreibung ein

Spydy
quelle
1
Das war hilfreich. Vielen Dank!!
Naval Hasan
Das war definitiv das, was ich verrückt machen wollte. Wenn Sie es nicht auf none setzen, können Sie nicht die richtige Größe sehen, die Sie in der sizeForItem-Methode angegeben haben.
Yusuf Kamil AK
1
Das Setzen der geschätzten Größe auf keine hat alles behoben
MMK
1
Thnx Einstellung geschätzte Größe auf keine durch Problem
behoben
2
Gute Lösung. Hier ist meine Diagnose dieser Frage nach Apples Dokumentation : UICollectionViewFlowLayoutscheint standardmäßig estimatedItemSizeauf UICollectionViewFlowLayout.automaticSizebei der Verwendung von IB , obwohl die Dokumentation sagt sollte es standardmäßig zu CGSizeZero. Wie Apple feststellt, automaticSize"werden Zellen mit Selbstgröße für Ihre Sammlungsansicht aktiviert." Aus diesem Grund bewirken andere Größenänderungen bei IB nichts.
Andrew Kirna
20

Endlich die Antwort bekommen. Sie sollten erweitern UICollectionViewDelegateFlowLayout
Dies sollte mit den obigen Antworten funktionieren.

Saburo
quelle
Könnten Sie ein Beispiel schreiben?
Mamdouh El Nakeeb
Eigentlich habe ich eine Erweiterung sowohl mit dem Datenquellen- als auch mit dem delegateFlowLayout-Protokoll erstellt und es hat nicht funktioniert. Was funktionierte, war die Trennung des FlowLayout-Teils von einer eigenen Erweiterung. Ich weiß nicht warum, aber es funktionierte in schnellem 3.
Skywalker
15

schnell 4.1

Sie haben zwei Möglichkeiten, um die Größe von CollectionView zu ändern.
Erster Weg -> füge dieses Protokoll hinzu UICollectionViewDelegateFlowLayout
für In meinem Fall möchte ich die Zelle in 3 Teile in einer Zeile teilen. Ich habe diesen Code unten gemacht

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

Zweiter Weg -> Sie müssen UICollectionViewDelegateFlowLayout nicht hinzufügen, sondern stattdessen Code in die viewDidload-Funktion als folgenden Code schreiben

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

Unabhängig davon, ob Sie einen Code als ersten oder zweiten Weg schreiben, erhalten Sie das gleiche Ergebnis wie oben. Ich schrieb es. Es hat bei mir funktioniert

Geben Sie hier die Bildbeschreibung ein

Sup.Ia.
quelle
2
Direkt von raywenderlich.com
Andrew
11

Größenverhältnis nach iPhone-Größe:

Folgendes können Sie tun, um die Breite und Höhe der Zellen in Bezug auf die iPhone-Größe zu variieren:

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

Und vielleicht sollten Sie auch Ihre AutoLayout-Einschränkungen für die Zelle deaktivieren, damit diese Antwort funktioniert.

AnthoPak
quelle
Ich habe dies und alle oben genannten Lösungen ausprobiert, aber der Inhalt einer Zelle wird nicht automatisch angepasst. Wie kann ich das beheben?
Biasi Wiga
7

Die Sammlungsansicht verfügt über ein Layoutobjekt . In Ihrem Fall ist es wahrscheinlich ein Fluss Layout ( UICollectionViewFlowLayout ). Legen Sie die itemSizeEigenschaft des Flusslayouts fest.

matt
quelle
Versuchte dies. gibt mir das gleiche Problem wie zuvor. Irgendwie ändert meine CollectionView die Größe und nicht meine Zellen.
JVS
2
Nun, es hängt alles davon ab, wann Sie es tun. Sie haben Ihren echten Code nicht angezeigt. Wer weiß also, was Sie tun? Ich versichere Ihnen, dass es funktioniert.
Matt
7

In Swift3 und Swift4 können Sie die Zellengröße ändern, indem Sie UICollectionViewDelegateFlowLayout hinzufügen und Folgendes implementieren:

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

Wenn Sie UICollectionView programmgesteuert erstellen, können Sie dies folgendermaßen tun:

    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)
Mohsen Mokhtari
quelle
4

swift4 swift 4 ios sammlungsansicht sammlungsansicht beispiel xcode aktueller code arbeitsprobe

Fügen Sie dies im Abschnitt "Delegieren" oben hinzu

UICollectionViewDelegateFlowLayout

und verwenden Sie diese Funktion

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

///// Beispiel für vollständigen Code

In Sammlungsansicht erstellen und Sammlungsansichtszelle im Storyboard geben Verweis auf die Sammlung als
@IBOutlet schwach var cvContent: UICollectionView!

Fügen Sie dies in den View Controller ein

 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
    }
}
Ullas Pujary
quelle
2

Versuchen Sie die folgende Methode

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

Swift 5 programmgesteuert

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)
    }()
Shubham Mishra
quelle
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.
Taka
quelle
1

2020, ganz einfacher Weg:

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource {

Sie müssen "UICollectionViewDelegateFlowLayout" hinzufügen, oder es erfolgt keine automatische Vervollständigung:

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource,
     UICollectionViewDelegateFlowLayout {

Geben Sie "sizeForItemAt ..." ein. Du bist fertig!

class YourCollection: UIViewController,
     UICollectionViewDelegate,
     UICollectionViewDataSource,
     UICollectionViewDelegateFlowLayout {

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

     return CGSize(width: 37, height: 63)
}

Das ist es.

Beispiel, wenn Sie möchten, dass "jede Zelle die gesamte Sammlungsansicht ausfüllt":

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

Eine andere Möglichkeit besteht darin, den Wert direkt im Ablauflayout festzulegen

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

Sie müssen also im Storyboard das Attribut für collectionView in der Zellenabschnittsschätzung auf keine festlegen, und in Ihrem ViewController benötigen Sie eine Delegate-Methode zum Implementieren dieser Methode: optional func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize

dgalluccio
quelle
0

Versuchen Sie, die UICollectionViewDelegateFlowLayout-Methode zu verwenden. In Xcode 11 oder höher müssen Sie die geschätzte Größe im Storyboard auf "Keine" setzen.

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)
}
Muhammad Shariq Hasnain
quelle
0

Ein einfacher Weg:

Wenn Sie nur eine einfache feste Größe benötigen :

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

Das ist alles dazu.

Ändern Sie im Storyboard einfach die Klasse von UICollectionView in SizedCollectionView.

Aber !!!

Beachten Sie, dass die Basisklasse dort "UI 'I' CollectionView" ist. 'I' für Initializer.

Es ist nicht so einfach, einer Sammlungsansicht einen Initialisierer hinzuzufügen. Hier ist ein gängiger Ansatz:

Sammlungsansicht ... mit Initialisierer:

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

In den meisten Projekten benötigen Sie "eine Sammlungsansicht mit einem Initialisierer". Sie werden also wahrscheinlich sowieso UIICollectionView(beachten Sie das zusätzliche I für Initializer!) In Ihrem Projekt haben.

Fattie
quelle
-4

Dies ist meine Version. Finden Sie Ihr geeignetes Verhältnis, um die Zellengröße gemäß Ihren Anforderungen zu erhalten.

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