UICollectionView marginesy odstępów

181

Mam zdjęcie, UICollectionViewktóre pokazuje. Utworzyłem widok kolekcji za pomocą UICollectionViewFlowLayout. Działa dobrze, ale chciałbym mieć odstępy na marginesach. Czy można to zrobić za pomocą, UICollectionViewFlowLayoutczy muszę zaimplementować własne UICollectionViewLayout?

Mert
źródło

Odpowiedzi:

332

Możesz użyć tej collectionView:layout:insetForSectionAtIndex:metody UICollectionViewlub ustawić sectionInsetwłaściwość UICollectionViewFlowLayoutobiektu dołączonego do UICollectionView:

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

lub

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

Zaktualizowano dla Swift 5

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
       return UIEdgeInsets(top: 25, left: 15, bottom: 0, right: 5)
    }
michael23
źródło
35
Nie wydaje mi się, żeby lewe i prawe wypustki działały, gdy używam pionowego układu przepływu ...
John
1
Teraz przesłanianie metody sectionInset podklasy UICollectionViewFlowLayout również nie ma wpływu. Ustawienie właściwości opisanej poniżej działa.
Dren
4
Uwaga: pamiętaj, aby dodać UICollectionViewDelegateFlowLayoutdo listy delegatów ViewController, aby użyć tej metodyinsetForSectionAtIndex
David Douglas,
98

Konfigurowanie wypustek w Konstruktorze interfejsów, jak pokazano na zrzucie ekranu poniżej

Ustawianie wstawek sekcji dla UICollectionView

Spowoduje to coś takiego:

Komórka widoku kolekcji z wypustkami przekroju

krzymar
źródło
2
Świetna odpowiedź, chciałem tylko zaznaczyć, że będziesz musiał także grać z minimalnymi odstępami, aby wstawka sekcji działała dobrze.
Smit Yash,
75

Aby dodać odstępy dla całego UICollectionView :

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

Aby bawić się odstępami między elementami tego samego wiersza (kolumny, jeśli przewijasz w poziomie) i ich rozmiarami:

flow.itemSize = ...;
flow.minimumInteritemSpacing = ...;
marmor
źródło
5
To działa, ale collection.collectionViewLayoutwymaga obsady, jak w przykładzie autorstwa @Pooja: UICollectionViewFlowLayout *flow = (UICollectionViewFlowLayout*) self.collectionViewLayout;
jwj
Szybka obsadaif let flow = collectionViewLayout as? UICollectionViewFlowLayout { flow.itemSize = CGSize(width: 100, height: 100) }
emily
41

Szybki 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

EDYTUJ XKod 11.4 i szybki 5

let flow = collectionView.collectionViewLayout as! UICollectionViewFlowLayout

nie działa Użyj poniższych prac.

let flow = UICollectionViewFlowLayout()

wprowadź opis zdjęcia tutaj

William Hu
źródło
Czy istnieje sposób, aby ustawić kolor odstępów?
Martín Serrano
1
@ MartínDaniel Wystarczy ustawić backgroundColorz collectionView. Lub cokolwiek super widok.
William Hu
1
ale na krawędziach nie ma marginesów
user924
@ user924 Marginesy na krawędziach można ustawić za pomocą UIEdgeInsets (góra: lewo: dół: prawo:). Jeśli przewijasz w pionie, ustaw lewe / prawe wstawki. Jeśli przewijasz w poziomie, ustaw górne i dolne wstawki.
Marcy
40

Aby poprawić nieprawidłowe informacje na tej stronie:

1- minimumInteritemSpacing : minimalny odstęp między elementami w tym samym rzędzie.

Wartość domyślna: 10,0.

(W przypadku siatki przewijanej pionowo ta wartość reprezentuje minimalne odstępy między elementami w tym samym rzędzie.)

2- minimumLineSpacing : minimalny odstęp między wierszami elementów na siatce.

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

Felix
źródło
2
Wydaje się, że nie wpływa to na odstępy między sekcjami, a jedynie pomiędzy elementami w tej samej sekcji?
Crashalot
@ Crashalot - czy na pewno nie masz na myśli minimumLineSpacing? tj. każda linia komórek? Istnieją również opcje wstawek przekroju, jeśli naprawdę używasz przekrojów.
Chucky,
To działało dla mnie, robiąc to za pośrednictwem interfejsu scenorysu. Szukałem rozwiązania dla widoków kolekcji tylko w poziomie. Dzięki +10
duch kemicofa
9

Nowoczesne szybkie, automatyczne obliczanie układu

Chociaż ten wątek zawiera już kilka przydatnych odpowiedzi, chcę dodać nowoczesną wersję Swift , opartą na odpowiedzi Williama Hu. Poprawia także dwie rzeczy:

  • Odstępy między różnymi liniami będą teraz zawsze odpowiadały odstępom między elementami w tej samej linii.
  • Ustawiając minimalną szerokość, kod automatycznie oblicza liczbę elementów w rzędzie i stosuje ten styl do układu przepływu.

Oto kod:

// 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
źródło
Jeśli itemsInOneLinewynosi 1, spowoduje to powstanie NaN z powodu dzielenia przez zero tutaj:itemsInOneLine / (itemsInOneLine - 1)
TylerJames
1
@TylerJames Thanks! Dostosowałem kod, aby rozwiązać problem;)
fredpi
8

użyj setMinimumLineSpacing:i setMinimumInteritemSpacing:na UICollectionViewFlowLayout-Object.

Jonathan Cichon
źródło
Nie, to nie działa zgodnie z oczekiwaniami. setMinimumLineSpacing to: Minimalny odstęp między elementami w tym samym rzędzie. A setMinimumInteritemSpacing to: Minimalny odstęp między wierszami elementów w siatce. Moje pytanie dotyczy marginesów, a nie odstępów między elementami. na przykład. Odstępy lewy i górny pierwszego elementu.
Mert
zakładając pionowy srollDirection, możesz użyć contentInset dla górnego i dolnego odstępu pierwszego i ostatniego wiersza. Możesz także dodać swoje marginesy do swoich komórek.
Jonathan Cichon,
8

Używanie collectionViewFlowLayout.sectionInsetlub collectionView:layout:insetForSectionAtIndex:są poprawne.

Jeśli jednak twoja kolekcjaView ma wiele sekcji i chcesz dodać margines do całej kolekcjiView, polecam użyć 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
źródło
5

Aby wstawić spację, CollectionItemużyj tego

napisz dwie linie w polu viewdidload

UICollectionViewFlowLayout *collectionViewLayout = (UICollectionViewFlowLayout*)self.collectionView.collectionViewLayout;
collectionViewLayout.sectionInset = UIEdgeInsetsMake(<CGFloat top>, <CGFloat left>, <CGFloat bottom>, <CGFloat right>)
Pooja Jalan
źródło
5

Ustaw insetForSectionAtwłaściwość UICollectionViewFlowLayoutobiektu dołączonego do twojegoUICollectionView

Pamiętaj, aby dodać ten protokół

UICollectionViewDelegateFlowLayout

Szybki

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

Cel C

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
    return UIEdgeInsetsMake(top, left, bottom, right);
}
PinkeshGjr
źródło
2

W celu 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;

Wszystko, co musisz zrobić, to zmienić wartość itemsPerRow i odpowiednio zaktualizuje liczbę elementów w wierszu. Co więcej, możesz zmienić wartość odstępów, jeśli chcesz mniej lub bardziej ogólne odstępy.

wprowadź opis zdjęcia tutaj wprowadź opis zdjęcia tutaj

ScottyBlades
źródło
1
Fajnie ... działa idealnie.
Soil
1

Aby dodać marginesy do określonych komórek, możesz użyć tego niestandardowego układu przepływu. 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
źródło
0

W swift 4 i autoLayout możesz użyć sectionInset w następujący sposób:

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
źródło
-1

Aby dodać 10px separację między każdą sekcją, po prostu napisz to

flowLayout.sectionInset = UIEdgeInsetsMake(0.0, 0.0,10,0);
Gal Blank
źródło
podczas korzystania z UICollectionReusableView rodzaju UICollectionElementKindSectionFooter, twoje rozwiązanie nie będzie działać
Pratik Jamariya
-1
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {       
         return UIEdgeInsetsMake(7, 10, 5, 10);    
   }
Vishal
źródło