UICollectionView-Abstandsränder

181

Ich habe eine, UICollectionViewdie Fotos zeigt. Ich habe die Sammlungsansicht mit erstellt UICollectionViewFlowLayout. Es funktioniert gut, aber ich hätte gerne Abstand an den Rändern. Ist das möglich UICollectionViewFlowLayoutoder muss ich mein eigenes implementieren UICollectionViewLayout?

Mert
quelle

Antworten:

331

Sie können die collectionView:layout:insetForSectionAtIndex:Methode für Ihre verwenden UICollectionViewoder die sectionInsetEigenschaft des UICollectionViewFlowLayoutan Ihre angehängten Objekts festlegen UICollectionView:

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
    return UIEdgeInsetsMake(top, left, bottom, right);
}

oder

UICollectionViewFlowLayout *aFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[aFlowLayout setSectionInset:UIEdgeInsetsMake(top, left, bottom, right)];

Aktualisiert für Swift 5

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
       return UIEdgeInsets(top: 25, left: 15, bottom: 0, right: 5)
    }
michael23
quelle
35
Ich scheine nicht die linken und rechten Einsätze zum Arbeiten zu bringen, wenn ich ein vertikales Flusslayout verwende ...
John
1
Das Überschreiben der sectionInset-Methode von UICollectionViewFlowLayout in Unterklassen hat jetzt ebenfalls keine Auswirkung. Die unten beschriebene Einstellungseigenschaft funktioniert.
Dren
4
NB: UICollectionViewDelegateFlowLayoutDenken Sie daran, Ihrer Liste der ViewController-Delegierten hinzuzufügen, um die Methode zu verwendeninsetForSectionAtIndex
David Douglas
98

Einrichten von Insets in Interface Builder wie im folgenden Screenshot gezeigt

Festlegen von Abschnittseinfügungen für UICollectionView

Wird zu so etwas führen:

Eine Sammlungsansichtszelle mit Abschnittseinfügungen

krzymar
quelle
2
Tolle Antwort, ich wollte nur darauf hinweisen, dass Sie auch mit minimalem Abstand spielen müssen, damit der Abschnittseinsatz gut funktioniert.
Smit Yash
75

So fügen Sie den gesamten Abstand hinzu UICollectionView:

UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*) collection.collectionViewLayout;
flow.sectionInset = UIEdgeInsetsMake(topMargin, left, bottom, right);

So spielen Sie mit dem Abstand zwischen Elementen derselben Zeile (Spalte, wenn Sie horizontal scrollen) und deren Größe:

flow.itemSize = ...;
flow.minimumInteritemSpacing = ...;
Marmor
quelle
5
Dies funktioniert, aber das collection.collectionViewLayoutbraucht eine Besetzung wie im Beispiel von @Pooja: UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*) self.collectionViewLayout;
jwj
Casting in schnellif let flow = collectionViewLayout as? UICollectionViewFlowLayout { flow.itemSize = CGSize(width: 100, height: 100) }
Emily
41

Swift 4

    let flow = collectionView.collectionViewLayout as! UICollectionViewFlowLayout // If you create collectionView programmatically then just create this flow by UICollectionViewFlowLayout() and init a collectionView by this flow.

    let itemSpacing: CGFloat = 3
    let itemsInOneLine: CGFloat = 3
    flow.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    let width = UIScreen.main.bounds.size.width - itemSpacing * CGFloat(itemsInOneLine - 1) //collectionView.frame.width is the same as  UIScreen.main.bounds.size.width here.
    flow.itemSize = CGSize(width: floor(width/itemsInOneLine), height: width/itemsInOneLine)
    flow.minimumInteritemSpacing = 3
    flow.minimumLineSpacing = 3

BEARBEITEN SIE XCode 11.4 und schnell 5

let flow = collectionView.collectionViewLayout as! UICollectionViewFlowLayout

funktioniert nicht Verwendung unten funktioniert.

let flow = UICollectionViewFlowLayout()

Geben Sie hier die Bildbeschreibung ein

William Hu
quelle
Gibt es eine Möglichkeit, die Farbe auf den Abstand einzustellen?
Martín Daniel
1
@ MartínDaniel Setze einfach das backgroundColorvon collectionView. Oder was auch immer die super Aussicht.
William Hu
1
aber es gibt keine Ränder an den Rändern
user924
@ user924 Ränder an Kanten können mit UIEdgeInsets festgelegt werden (oben: links: unten: rechts :). Wenn Sie vertikal scrollen, stellen Sie die linken / rechten Einfügungen ein. Wenn Sie horizontal scrollen, stellen Sie die oberen und unteren Einfügungen ein.
Marcy
40

Nur um einige falsche Informationen auf dieser Seite zu korrigieren:

1- MinimumInteritemSpacing : Der minimale Abstand zwischen Elementen in derselben Zeile.

Der Standardwert: 10.0.

(Bei einem vertikal scrollenden Raster stellt dieser Wert den Mindestabstand zwischen Elementen in derselben Zeile dar.)

2- MinimumLineSpacing : Der minimale Abstand zwischen Zeilen von Elementen im Raster.

Ref: http://developer.apple.com/library/ios/#documentation/uikit/reference/UICollectionViewFlowLayout_class/Reference/Reference.html

Felix
quelle
2
Dies scheint den Abstand zwischen Abschnitten nicht zu beeinflussen, nur zwischen Elementen innerhalb desselben Abschnitts?
Crashalot
@Crashalot - bist du sicher, dass du nicht MinimumLineSpacing meinst? dh jede Zelllinie? Es gibt auch Optionen für Abschnittseinfügungen, wenn Sie wirklich Abschnitte verwenden.
Chucky
Dies funktionierte für mich über die Storyboard-Oberfläche. Ich suchte nach einer Lösung für nur horizontale Sammlungsansichten. Vielen Dank +10
kemicofa Ghost
9

Moderne schnelle, automatische Layoutberechnung

Während dieser Thread bereits eine Reihe nützlicher Antworten enthält, möchte ich eine moderne Swift-Version hinzufügen , die auf der Antwort von William Hu basiert. Es verbessert auch zwei Dinge:

  • Der Abstand zwischen verschiedenen Zeilen stimmt jetzt immer mit dem Abstand zwischen Elementen in derselben Zeile überein.
  • Durch Festlegen einer Mindestbreite berechnet der Code automatisch die Anzahl der Elemente in einer Zeile und wendet diesen Stil auf das Ablauflayout an.

Hier ist der Code:

// Create flow layout
let flow = UICollectionViewFlowLayout()

// Define layout constants
let itemSpacing: CGFloat = 1
let minimumCellWidth: CGFloat = 120
let collectionViewWidth = collectionView!.bounds.size.width

// Calculate other required constants
let itemsInOneLine = CGFloat(Int((collectionViewWidth - CGFloat(Int(collectionViewWidth / minimumCellWidth) - 1) * itemSpacing) / minimumCellWidth))
let width = collectionViewWidth - itemSpacing * (itemsInOneLine - 1)
let cellWidth = floor(width / itemsInOneLine)
let realItemSpacing = itemSpacing + (width / itemsInOneLine - cellWidth) * itemsInOneLine / max(1, itemsInOneLine - 1))

// Apply values
flow.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
flow.itemSize = CGSize(width: cellWidth, height: cellWidth)
flow.minimumInteritemSpacing = realItemSpacing
flow.minimumLineSpacing = realItemSpacing

// Apply flow layout
collectionView?.setCollectionViewLayout(flow, animated: false)
Fredpi
quelle
Wenn itemsInOneLine1 ist, führt dies zu einer NaN, da hier durch Null geteilt wird:itemsInOneLine / (itemsInOneLine - 1)
TylerJames
1
@ TylerJames Danke! Ich habe den Code angepasst, um das Problem zu beheben;)
fredpi
8

benutze setMinimumLineSpacing:und setMinimumInteritemSpacing:auf dem UICollectionViewFlowLayout-Object.

Jonathan Cichon
quelle
Nein, es funktioniert nicht wie erwartet. setMinimumLineSpacing ist: Der minimale Abstand zwischen Elementen in derselben Zeile. Und setMinimumInteritemSpacing ist: Der minimale Abstand zwischen Zeilen von Elementen im Raster. Meine Frage bezieht sich auf Ränder, nicht auf Leerzeichen zwischen Elementen. z.B. Linker und oberer Abstand des ersten Elements.
Mert
Unter der Annahme einer vertikalen srollDirection können Sie contentInset für den oberen und unteren Abstand der ersten und letzten Zeile verwenden. Sie können auch Ihre Ränder in Ihre Zellen einfügen.
Jonathan Cichon
8

Verwenden collectionViewFlowLayout.sectionInsetoder collectionView:layout:insetForSectionAtIndex:sind richtig.

Wenn Ihre collectionView jedoch mehrere Abschnitte enthält und Sie der gesamten collectionView einen Rand hinzufügen möchten, empfehle ich die Verwendung des scrollView contentInset:

UIEdgeInsets collectionViewInsets = UIEdgeInsetsMake(50.0, 0.0, 30.0, 0.0);
self.collectionView.contentInset = collectionViewInsets;
self.collectionView.scrollIndicatorInsets = UIEdgeInsetsMake(collectionViewInsets.top, 0, collectionViewInsets.bottom, 0);
vmeyer
quelle
5

CollectionItemVerwenden Sie dies, um Platz zwischen s zu setzen

Schreiben Sie diese beiden Zeilen in viewdidload

UICollectionViewFlowLayout *collectionViewLayout = (UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout;
collectionViewLayout.sectionInset = UIEdgeInsetsMake(<CGFloat top>, <CGFloat left>, <CGFloat bottom>, <CGFloat right>)
Pooja Jalan
quelle
5

Legen Sie die insetForSectionAtEigenschaft des UICollectionViewFlowLayoutan Ihr angehängten Objekts festUICollectionView

Stellen Sie sicher, dass Sie dieses Protokoll hinzufügen

UICollectionViewDelegateFlowLayout

Schnell

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

Ziel c

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
    return UIEdgeInsetsMake(top, left, bottom, right);
}
PinkeshGjr
quelle
2

In Ziel-C

CGFloat spacing = 5;
UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*)_habbitCollectionV.collectionViewLayout;
flow.sectionInset = UIEdgeInsetsMake(0, spacing, 0, spacing);
CGFloat itemsPerRow = 2;
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat oneMore = itemsPerRow + 1;
CGFloat width = screenRect.size.width - spacing * oneMore;
CGFloat height = width / itemsPerRow;

flow.itemSize = CGSizeMake(floor(height), height);
flow.minimumInteritemSpacing = spacing;
flow.minimumLineSpacing = spacing;

Sie müssen lediglich den Wert für itemsPerRow ändern und die Anzahl der Elemente pro Zeile entsprechend aktualisieren. Darüber hinaus können Sie den Abstandswert ändern, wenn Sie mehr oder weniger allgemeinen Abstand wünschen.

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

ScottyBlades
quelle
1
Schön ... es ist perfekt.
Sohil
1

Zum Hinzufügen von Rändern zu bestimmten Zellen können Sie dieses benutzerdefinierte Ablauflayout verwenden. https://github.com/voyages-sncf-technologies/VSCollectionViewCellInsetFlowLayout/

extension ViewController : VSCollectionViewDelegateCellInsetFlowLayout 
{
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForItemAt indexPath: IndexPath) -> UIEdgeInsets {
        if indexPath.item == 0 {
            return UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
        }
        return UIEdgeInsets.zero
    }
}
Myrddin
quelle
0

In Swift 4 und AutoLayout können Sie sectionInset wie folgt verwenden :

let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .vertical
        layout.itemSize = CGSize(width: (view.frame.width-40)/2, height: (view.frame.width40)/2) // item size
        layout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10) // here you can add space to 4 side of item
        collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: layout) // set layout to item
        collectionView?.register(ProductCategoryCell.self, forCellWithReuseIdentifier: cellIdentifier) // registerCell
        collectionView?.backgroundColor = .white // background color of UICollectionView
        view.addSubview(collectionView!) // add UICollectionView to view
Mohsen Mokhtari
quelle
-1

Um einen Abstand von 10 Pixel zwischen den einzelnen Abschnitten hinzuzufügen, schreiben Sie dies einfach

flowLayout.sectionInset = UIEdgeInsetsMake(0.0, 0.0,10,0);
Gal Blank
quelle
Wenn Sie UICollectionReusableView der Art UICollectionElementKindSectionFooter verwenden, funktioniert Ihre Lösung nicht
Pratik Jamariya
-1
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {       
         return UIEdgeInsetsMake(7, 10, 5, 10);    
   }
vishal
quelle