Wie stelle ich den Zellenabstand und das Größenverhältnis von UICollectionView - UICollectionViewFlowLayout ein?

137

Ich versuche , hinzufügen UICollectionViewzu ViewController, und ich brauche 3 - Zellen haben ‚pro Zeile‘ ohne Leerzeichen zwischen den Zellen (wie ein Gitter aussehen soll). Die Zellenbreite sollte ein Drittel der Bildschirmgröße betragen, daher dachte ich, dass die layout.itemBreite gleich sein sollte. Aber dann verstehe ich das:

layout.itemSize width = screenSize.width / 3

Wenn ich diese Größe reduziere ( z. B. um 7 oder 8 Pixel ), ist es besser, aber die dritte Zelle in der Reihe ist nicht vollständig sichtbar, und ich habe immer noch diese Leerstelle (oben und unten sowie links und rechts).

Geben Sie hier die Bildbeschreibung ein

class ViewController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
    var collectionView: UICollectionView?
    var screenSize: CGRect!
    var screenWidth: CGFloat!
    var screenHeight: CGFloat!

    override func viewDidLoad() {
        super.viewDidLoad()

        screenSize = UIScreen.mainScreen().bounds
        screenWidth = screenSize.width
        screenHeight = screenSize.height

        // Do any additional setup after loading the view, typically from a nib
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 20, left: 0, bottom: 10, right: 0)
        layout.itemSize = CGSize(width: screenWidth / 3, height: screenWidth / 3)
        collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
        collectionView!.dataSource = self
        collectionView!.delegate = self
        collectionView!.registerClass(CollectionViewCell.self, forCellWithReuseIdentifier: "CollectionViewCell")
        collectionView!.backgroundColor = UIColor.greenColor()
        self.view.addSubview(collectionView!)
    }

    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 20
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as CollectionViewCell
        cell.backgroundColor = UIColor.whiteColor()
        cell.layer.borderColor = UIColor.blackColor().CGColor
        cell.layer.borderWidth = 0.5
        cell.frame.size.width = screenWidth / 3
        cell.frame.size.height = screenWidth / 3

        cell.textLabel?.text = "\(indexPath.section):\(indexPath.row)"
        return cell
    }
}
Marko
quelle
Hier ist Ihre Lösung. Vielen Dank.
Janu Kansagra
Hier ist Arbeitscode
Nikunj Kumbhani

Antworten:

299

Fügen Sie diese 2 Zeilen hinzu

layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0

Also hast du:

   // Do any additional setup after loading the view, typically from a nib.
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets(top: 20, left: 0, bottom: 10, right: 0)
        layout.itemSize = CGSize(width: screenWidth/3, height: screenWidth/3)
        layout.minimumInteritemSpacing = 0
        layout.minimumLineSpacing = 0
        collectionView!.collectionViewLayout = layout

Dadurch werden alle Leerzeichen entfernt und Sie erhalten ein Rasterlayout:

Geben Sie hier die Bildbeschreibung ein

Wenn die erste Spalte eine Breite haben soll, die der Bildschirmbreite entspricht, fügen Sie die folgende Funktion hinzu:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    if indexPath.row == 0
    {
        return CGSize(width: screenWidth, height: screenWidth/3)
    }
    return CGSize(width: screenWidth/3, height: screenWidth/3);

}

Das Rasterlayout sieht nun folgendermaßen aus (ich habe der ersten Zelle auch einen blauen Hintergrund hinzugefügt): Geben Sie hier die Bildbeschreibung ein

Peter Todd
quelle
Vielen Dank, ich hatte etwas viel Komplizierteres erwartet und zu viel Zeit damit verbracht. Nochmals vielen Dank.
Marko
Und nur noch eins: Gibt es eine Möglichkeit, layout.itemSize nur für die erste Zelle zu ändern ? (Ich weiß, dass ich cell.frame.size ändern muss, wenn indexPath.row 0 ist, weiß aber nicht, wie ich die Layoutgröße nur für ein Element ändern soll . ) Die erste Elementbreite sollte gleich screenWidth sein .
Marko
1
Hallo, ich habe das gleiche Problem, aber ich möchte den ähnlichen Funktionstitel in Ziel C kennen.
Nada Gamal
1
Ok, es funktioniert jetzt gut. Vielen Dank :) Ziel C-Funktion: - (CGSize) collectionView: (UICollectionView ) collectionView-Layout: (UICollectionViewLayout ) collectionViewLayout sizeForItemAtIndexPath: (NSIndexPath *) indexPath {return CGSizeMake (screenWidth / 3, ); }
Nada Gamal
4
danke für die tolle antwort @greentor. schickte ein Kopfgeld. Vergessen Sie nicht die collectionView! .CollectionViewLayout = Layout , Leser
Fattie
46

Für Swift 3 und XCode 8 funktionierte dies. Führen Sie die folgenden Schritte aus, um dies zu erreichen: -

{
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    let width = UIScreen.main.bounds.width
    layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
    layout.itemSize = CGSize(width: width / 2, height: width / 2)
    layout.minimumInteritemSpacing = 0
    layout.minimumLineSpacing = 0
    collectionView!.collectionViewLayout = layout
}

Fügen Sie diesen Code in die Funktion viewDidLoad () ein.

Nirmit Dagly
quelle
32

In bestimmten Situationen wirkt sich das Festlegen von UICollectionViewFlowLayoutin viewDidLoadoder ViewWillAppearmöglicherweise nicht auf die collectionView aus.

Die Einstellung UICollectionViewFlowLayoutin viewDidAppearkann bewirken , dass die Veränderungen der Zellen Größen im laufenden Betrieb sehen.

Eine andere Lösung in Swift 3:

extension YourViewController : UICollectionViewDelegateFlowLayout{

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: 20, left: 0, bottom: 10, right: 0)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let collectionViewWidth = collectionView.bounds.width
        return CGSize(width: collectionViewWidth/3, height: collectionViewWidth/3)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 20
    }
}
Maor
quelle
Gute Antwort! Dies ist definitiv der Apple-Weg, dies zu tun. Jetzt wissen Sie nicht, wie Sie aktualisieren sollen, wenn das Gerät die Ausrichtung ändert, oder?
jlstr
17

Wenn Sie nach Swift 3 suchen, befolgen Sie die folgenden Schritte, um dies zu erreichen:

func viewDidLoad() {

    //Define Layout here
    let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()

    //Get device width
    let width = UIScreen.main.bounds.width

    //set section inset as per your requirement.
    layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)

    //set cell item size here 
    layout.itemSize = CGSize(width: width / 2, height: width / 2)

    //set Minimum spacing between 2 items
    layout.minimumInteritemSpacing = 0

    //set minimum vertical line spacing here between two lines in collectionview
    layout.minimumLineSpacing = 0

    //apply defined layout to collectionview
    collectionView!.collectionViewLayout = layout

}

Dies wird auf Xcode 8.0 mit Swift 3 überprüft.

Dharmendra Kachhadiya
quelle
8
let layout = myCollectionView.collectionViewLayout as? UICollectionViewFlowLayout
layout?.minimumLineSpacing = 8
Jamal Zare
quelle
4

Swift 4

let collectionViewLayout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout
collectionViewLayout?.sectionInset = UIEdgeInsetsMake(0, 20, 0, 40) 
collectionViewLayout?.invalidateLayout()
Alfi
quelle
1

Für Swift 3 und XCode 8 funktionierte dies. Führen Sie die folgenden Schritte aus, um dies zu erreichen: -

viewDidLoad()
    {
        let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        var width = UIScreen.main.bounds.width
        layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
    width = width - 10
    layout.itemSize = CGSize(width: width / 2, height: width / 2)
        layout.minimumInteritemSpacing = 0
        layout.minimumLineSpacing = 0
        collectionView!.collectionViewLayout = layout
    }
Moin Shirazi
quelle
3
Wie man die Tatsache berücksichtigt, wenn Sie mehrere Abschnitte haben
Nikhil Pandey
es ist nur für 1 Spalte (Abschnitt)
user924
0

Für Swift 3+ und Xcode 9+ Versuchen Sie dies

extension ViewController: UICollectionViewDelegateFlowLayout {

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

    let collectionWidth = collectionView.bounds.width
    return CGSize(width: collectionWidth/3, height: collectionWidth/3)

}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 0
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 0

}
Aditya
quelle