Penspasian sel di UICollectionView

197

Bagaimana cara mengatur spasi sel di bagian UICollectionView? Saya tahu ada properti yang minimumInteritemSpacingtelah saya atur ke 5.0 masih spasi tidak muncul 5.0. Saya telah menerapkan metode delegasi flowout.

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{

    return 5.0;
}

masih saya tidak mendapatkan hasil yang diinginkan. Saya pikir ini jarak minimum. Apakah tidak ada cara saya mengatur jarak maksimum?

simulator sc

Vishal Singh
sumber
apakah Anda memeriksa apakah sedang memasukkan metode delegasi atau tidak ..? dengan meletakkan breakpoint ..
Prashant Nikam
ya itu memasuki delegasi, di IB juga saya telah mengatur jarak sel min ke 5. Tapi saya tidak berpikir ruang minimum adalah properti yang akan membantu saya karena hanya akan memastikan bahwa ruang minimum antara sel harus 5, tetapi jika tampilan koleksi memiliki ruang ekstra, maka akan menggunakan ruang ekstra itu. Harus ada sesuatu seperti spasi sel maksimum
Vishal Singh
Saya memiliki masalah yang sama. 5px sepertinya tidak berfungsi. Intresstingly saya bisa melakukan ini dengan UITableView, tetapi tidak dengan UICollectionView ...
jerik
Saya telah memperbaikinya dengan melakukan beberapa perhitungan .. saya akan mempostingnya besok. :)
Vishal Singh
CATATAN UNTUK 2016 ini mudah: stackoverflow.com/a/28327193/294884
Fattie

Jawaban:

145

Saya tahu topiknya sudah lama, tetapi siapa tahu masih perlu jawaban yang benar di sini apa yang Anda butuhkan:

  1. Timpa tata letak aliran standar.
  2. Tambahkan implementasi seperti itu:

    - (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {
        NSArray *answer = [super layoutAttributesForElementsInRect:rect];
    
        for(int i = 1; i < [answer count]; ++i) {
            UICollectionViewLayoutAttributes *currentLayoutAttributes = answer[i];
            UICollectionViewLayoutAttributes *prevLayoutAttributes = answer[i - 1];
            NSInteger maximumSpacing = 4;
            NSInteger origin = CGRectGetMaxX(prevLayoutAttributes.frame);
    
            if(origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize.width) {
                CGRect frame = currentLayoutAttributes.frame;
                frame.origin.x = origin + maximumSpacing;
                currentLayoutAttributes.frame = frame;
            }
        }
        return answer;
    }
    

di mana maksimumSpasi dapat diatur ke nilai apa pun yang Anda inginkan. Trik ini menjamin bahwa ruang antar sel akan PERSIS sama dengan spasi maksimum !!

iago849
sumber
Jadi, di mana kita meletakkan ini?
Jonny
1
Hei Jonny, mewarisi dari Tata Letak Alur standar dan cukup salin dan tempel metode ini ke kelas Anda.
iago849
1
Perhatikan bahwa Anda tidak perlu membuat mutableCopy: Anda tidak mengubah konten array, tetapi memutasikan objek di dalamnya.
Brock Boland
5
mungkin saya melakukan sesuatu yang salah atau ide ini tidak bekerja untuk 100%, karena ketika saya gulir sampai akhir saya melihat bahwa beberapa sel saling overlay :(
pash3r
2
Pos yang bagus. Saya memang menemukan kesalahan dengan itu mengganggu pemformatan baris terakhir tata letak dalam beberapa keadaan. Untuk menyelesaikannya saya mengubah ifke DAN kondisi tambahan: if(origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize.width && currentLayoutAttributes.frame.origin.x > prevLayoutAttributes.frame.origin.x) {
chrisoneiota
190

Mendukung pertanyaan awal. Saya mencoba untuk mendapatkan jarak ke 5px pada UICollectionViewtetapi ini tidak berhasil, juga dengan UIEdgeInsetsMake(0,0,0,0)...

Pada UITableView saya bisa melakukan ini dengan secara langsung menentukan koordinat x, y berturut-turut ...

masukkan deskripsi gambar di sini

Inilah kode UICollectionView saya:

#pragma mark collection view cell layout / size
- (CGSize)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return [self getCellSize:indexPath];  // will be w120xh100 or w190x100
    // if the width is higher, only one image will be shown in a line
}

#pragma mark collection view cell paddings
- (UIEdgeInsets)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    return UIEdgeInsetsMake(0, 0, 0, 0); // top, left, bottom, right
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {

    return 5.0;
}

Pembaruan: Memecahkan masalah saya, dengan kode berikut.

masukkan deskripsi gambar di sini

ViewController.m

#import "ViewController.h"
#import "MagazineCell.h" // created just the default class. 

static NSString * const cellID = @"cellID";

@interface ViewController ()

@end

@implementation ViewController

#pragma mark - Collection view
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 30;
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MagazineCell *mCell = (MagazineCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];

    mCell.backgroundColor = [UIColor lightGrayColor];

    return mCell;
}

#pragma mark Collection view layout things
// Layout: Set cell size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {

    NSLog(@"SETTING SIZE FOR ITEM AT INDEX %d", indexPath.row);
    CGSize mElementSize = CGSizeMake(104, 104);
    return mElementSize;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
    return 2.0;
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
    return 2.0;
}

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

@end
jerik
sumber
Ini jawaban yang jauh lebih baik. Lihatlah callback yang bisa Anda sesuaikan di UICollectionViewDelegateFlowLayout dan Anda bisa melihat bagaimana ini bisa di-tweak.
cynistersix
1
Saya kira ini hanya bisa bekerja ketika lebar item + spasi sama dengan lebar uicollectionview.
xi.lin
@JayprakashDubey saat ini saya tidak cocok dengan cepat. Kamu harus mencobanya. Semoga sukses
jerik
Di mana Anda menentukan lebar antara sel-sel 5px?
UKDataGeek
1
Jawaban yang jauh lebih baik daripada yang diterima, terutama karena subclassing UICollectionViewLayout hanya untuk mengganti satu metode sepertinya berlebihan, dan tidak ada masalah sepele mengingat semua metode lain yang perlu diganti.
Cindeselia
80

Menggunakan tata letak aliran horizontal, saya juga mendapatkan jarak 10 poin antar sel. Untuk menghapus spasi yang saya perlu atur minimumLineSpacingjuga minimumInterItemSpacingke nol.

UICollectionViewFlowLayout *flow = [[UICollectionViewFlowLayout alloc] init];
flow.itemSize = CGSizeMake(cellWidth, cellHeight);
flow.scrollDirection = UICollectionViewScrollDirectionHorizontal;
flow.minimumInteritemSpacing = 0;
flow.minimumLineSpacing = 0;

Juga, jika semua sel Anda memiliki ukuran yang sama, lebih mudah dan lebih efisien untuk mengatur properti pada tata letak aliran secara langsung daripada menggunakan metode delegasi.

Jason Moore
sumber
34
Secara mengejutkan, minimumLineSpacing memengaruhi ruang horizontal antar sel.
Matt H
4
SAYA juga, saya perlu gulir horizontal dan spasi nol antara sel, dan minimumLineSpacing = 0 adalah kuncinya.
Wingzero
3
Saya bisa mendapatkan efek ini tanpa menggunakan minimumInteritemSpacing. Hanya pengaturan minimumLineSpacing = 0tata letak horizontal saya menghapus jarak horizontal antara item.
Ziewvater
1
Jika Anda memikirkannya, jarak horizontal antara item adalah garis spasi untuk tata letak yang mengalir secara horizontal. Spasi garis adalah jarak vertikal antara item dalam tata letak tipikal yang mengalir secara vertikal.
lancejabr
62

Ingat, ini adalah ruang baris minimum , bukan spasi antar item minimum atau ruang sel. Karena arah gulir collectionView Anda adalah HORIZONTAL .

Jika vertikal maka Anda perlu mengatur ruang sel atau ruang antar item untuk ruang horizontal antara sel dan spasi garis untuk ruang vertikal antara sel.

Versi objektif-C

- (CGFloat)collectionView:(UICollectionView *)collectionView
                       layout:(UICollectionViewLayout*)collectionViewLayout
    minimumLineSpacingForSectionAtIndex:(NSInteger)section
    {
        return 20;
    }

Versi cepat:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 20
}
Vincent Joy
sumber
sekarang ruang bawah hilang ketika saya mengembalikan 0; bagaimana cara menghapus ruang sisi kanan?
Bangalore
Hei, saya tidak mengerti pertanyaan Anda dengan sangat baik. Tapi saya pikir insetForSectionAtIndex adalah apa yang Anda cari. - (UIEdgeInsets) collectionView: (UICollectionView *) layout layoutView: (UICollectionViewLayout *) collectionViewLayout insetForSectionAtIndex: (NSInteger) bagian {return UIEdgeInsetsMake (5, 10, 5, 10); }
Vincent Joy
Ini adalah jarak garis minimum untuk horizontal dan vertikal.
Swati
Anda menyelamatkan hari saya (Y).
Umair_UAS
Astaga! Saya tidak percaya ini. Terima kasih
Magoo
36

Coba kode ini untuk memastikan Anda memiliki jarak 5px antara setiap item:

- (UIEdgeInsets)collectionView:(UICollectionView *) collectionView 
                        layout:(UICollectionViewLayout *) collectionViewLayout 
        insetForSectionAtIndex:(NSInteger) section {

    return UIEdgeInsetsMake(0, 0, 0, 5); // top, left, bottom, right
}

- (CGFloat)collectionView:(UICollectionView *) collectionView
                   layout:(UICollectionViewLayout *) collectionViewLayout
  minimumInteritemSpacingForSectionAtIndex:(NSInteger) section {    
    return 5.0;
}
LASoft
sumber
Harap format kode Anda sebagai blok kode sehingga akan ditampilkan dengan baik di SO.
Saluran
33

Swift versi jawaban yang paling populer. Ruang antar sel akan sama dengan cellSpacing.

class CustomViewFlowLayout : UICollectionViewFlowLayout {

    let cellSpacing:CGFloat = 4

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        if let attributes = super.layoutAttributesForElementsInRect(rect) {
        for (index, attribute) in attributes.enumerate() {
                if index == 0 { continue }
                let prevLayoutAttributes = attributes[index - 1]
                let origin = CGRectGetMaxX(prevLayoutAttributes.frame)
                if(origin + cellSpacing + attribute.frame.size.width < self.collectionViewContentSize().width) {
                    attribute.frame.origin.x = origin + cellSpacing
                }
            }
            return attributes
        }
        return nil
    }
}
Vojtech Vrbka
sumber
super.layoutAttributesForElements (in: rect) mengembalikan nihil ide?
Ashok R
Seperti semua metode lain yang menggunakan ini, ini tidak berfungsi dengan baik untuk beberapa baris. Kesenjangan intermittent, rounding-error-style akan tetap ada di antara baris, bahkan dengan metode dan properti delegasi yang tepat diatur untuk menggunakan 0. Ini mungkin merupakan masalah rendering UICollectionView.
Womble
30

Saya telah menemukan cara yang sangat mudah untuk mengkonfigurasi jarak antar sel atau baris dengan menggunakan IB.

Cukup pilih UICollectionView dari storyboard / file Xib dan klik Ukuran Inspektur seperti yang ditentukan dalam gambar di bawah ini.

masukkan deskripsi gambar di sini

Untuk mengonfigurasi ruang secara terprogram gunakan properti berikut.

1) Untuk mengatur ruang antar baris.

[self.collectionView setMinimumLineSpacing:5];

2) Untuk mengatur ruang antar item / sel.

[self.collectionView setMinimumInteritemSpacing:5];
Aamir
sumber
1
Itu ruang minimum, yang akan lebih besar dari nilai yang ditentukan dan tidak selalu nilai yang ditentukan.
Vishal Singh
21

Harap perhatikan nama properti minimumInterItemSpacing . Ini akan menjadi jarak minimum antara item bukan spasi yang tepat . Jika Anda menetapkan minimumInterItemSpacing ke beberapa nilai, Anda dapat memastikan bahwa spasi tidak akan menjadi nilai yang kurang dari itu. Namun ada peluang mendapatkan nilai yang lebih tinggi.

Sebenarnya jarak antar item tergantung pada beberapa faktor itemSize dan sectionInset . Tampilan koleksi secara dinamis menempatkan konten berdasarkan nilai-nilai ini. Jadi Anda tidak bisa memastikan jarak yang tepat. Anda harus melakukan beberapa percobaan dan kesalahan dengan sectionInset dan minimumInterItemSpacing .

Anil Varghese
sumber
1
@Semua serangga tepi? : D
NightFury
10
Mungkin ada bug di bagian Anda.
Nestor
24
serangga == bug && serangga! = inset :)
Nestor
16

Jawaban untuk Swift 3.0, Xcode 8

1. Pastikan Anda mengatur delegasi tampilan koleksi

class DashboardViewController: UIViewController {
    @IBOutlet weak var dashboardCollectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        dashboardCollectionView.delegate = self
    }
}

2.Implement UICollectionViewDelegateFlowLayout protokol, tidak UICollectionViewDelegate.

extension DashboardViewController: UICollectionViewDelegateFlowLayout {
    fileprivate var sectionInsets: UIEdgeInsets {
        return .zero
    }

    fileprivate var itemsPerRow: CGFloat {
        return 2
    }

    fileprivate var interitemSpace: CGFloat {
        return 5.0
    }

    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {
        let sectionPadding = sectionInsets.left * (itemsPerRow + 1)
        let interitemPadding = max(0.0, itemsPerRow - 1) * interitemSpace
        let availableWidth = collectionView.bounds.width - sectionPadding - interitemPadding
        let widthPerItem = availableWidth / itemsPerRow

        return CGSize(width: widthPerItem, height: widthPerItem)
    }

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

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

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return interitemSpace
    }
}
Vadim Bulavin
sumber
1
Pikir Anda dapat menghapus publik di sana. Harus bekerja dengan baik, dan konsisten dengan semua fungsi lainnya.
Edward Potter
Apakah ini berfungsi untuk tampilan koleksi gulir vertikal? Saya memiliki tampilan koleksi di mana seharusnya menampilkan 2 sel secara horizontal pada perangkat seperti iPhone 6s dan 6s Plus, tetapi harus menunjukkan hanya satu sel untuk apa pun yang lebih rendah dari itu yaitu 5s, 5 dan SE. Kode saya saat ini berfungsi, tetapi pada perangkat 6s Plus, jarak antar sel terlalu banyak dan terlihat jelek dan saya mencoba mengurangi celah itu dan itu satu-satunya persyaratan karena semua perangkat lain bekerja sesuai desain saya.
AnBisw
11

Kode sederhana untuk spasi

let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.minimumInteritemSpacing = 10 // Some float value
AMayes
sumber
3
Untuk spasi sel horizontal harus menggunakan: minimumLineSpacing
Alfi
9

The sebagai jawaban (dan juga versi cepat ) memiliki masalah kecil: akan ada jarak yang besar di sebelah kanan.

Ini karena tata letak aliran disesuaikan untuk membuat jarak sel yang tepat, dengan perilaku kiri mengambang .

Solusi saya adalah memanipulasi inset bagian, sehingga bagian tersebut sejajar pusat, namun jaraknya persis seperti yang ditentukan.

Pada tangkapan layar di bawah ini, jarak item / garis persis 8pt, sedangkan bagian kiri & kanan akan lebih besar dari 8pt (untuk membuatnya rata tengah):

sel spasi secara merata

Kode cepat seperti itu:

private let minItemSpacing: CGFloat = 8
private let itemWidth: CGFloat      = 100
private let headerHeight: CGFloat   = 32

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    // Create our custom flow layout that evenly space out the items, and have them in the center
    let layout = UICollectionViewFlowLayout()
    layout.itemSize = CGSize(width: itemWidth, height: itemWidth)
    layout.minimumInteritemSpacing = minItemSpacing
    layout.minimumLineSpacing = minItemSpacing
    layout.headerReferenceSize = CGSize(width: 0, height: headerHeight)

    // Find n, where n is the number of item that can fit into the collection view
    var n: CGFloat = 1
    let containerWidth = collectionView.bounds.width
    while true {
        let nextN = n + 1
        let totalWidth = (nextN*itemWidth) + (nextN-1)*minItemSpacing
        if totalWidth > containerWidth {
            break
        } else {
            n = nextN
        }
    }

    // Calculate the section inset for left and right. 
    // Setting this section inset will manipulate the items such that they will all be aligned horizontally center.
    let inset = max(minItemSpacing, floor( (containerWidth - (n*itemWidth) - (n-1)*minItemSpacing) / 2 ) )
    layout.sectionInset = UIEdgeInsets(top: minItemSpacing, left: inset, bottom: minItemSpacing, right: inset)

    collectionView.collectionViewLayout = layout
}
samwize
sumber
1
Saya mendapatkan 'NSInvalidArgumentException', alasan: '*** setObjectForKey: objek tidak boleh nol (kunci: <NSIndexPath: 0xc00000000000000016> {length = 2, path = 0 - 0})' pengecualian tanpa peringatan.
DaftWooly
... jika saya tidak salah, loop sementara Anda setara dengan: let n = Int((containerWidth + minItemSpacing)/((itemWidth+minItemSpacing)))
DaftWooly
Tidak menggunakan kode seperti apa adanya, tetapi ini memberi saya referensi terbaik untuk menerapkan tata letak aliran keluar saya untuk tampilan koleksi. sorak-sorai
Dima Gimburg
8

Tetapkan UICollectionViewDelegateFlowLayoutprotokol di file header Anda.

Terapkan metode UICollectionViewDelegateFlowLayoutprotokol berikut ini:

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

Klik Di Sini untuk melihat Dokumentasi Apple tentang UIEdgeInsetMakemetode.

Salman Zaidi
sumber
4

Pendekatan Storyboard

Pilih CollectionView di storyboard Anda dan pergi ke inspektur ukuran dan mengatur spasi min untuk sel dan garis sebagai 5

Swift 5 Secara terprogram

lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal

        //Provide Width and Height According to your need
        let width = UIScreen.main.bounds.width / 4
        let height = UIScreen.main.bounds.height / 10
        layout.itemSize = CGSize(width: width, height: height)

        //For Adjusting the cells spacing
        layout.minimumInteritemSpacing = 5
        layout.minimumLineSpacing = 5

        return UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
    }()
Shubham Mishra
sumber
3

Jika Anda ingin mengubah jarak tanpa menyentuh ukuran sel yang sebenarnya, ini adalah solusi yang paling cocok untuk saya. #xcode 9 # tvOS11 # iOS11 #swift

Jadi di UICollectionViewDelegateFlowLayout , ubah implementasikan metode selanjutnya, triknya adalah Anda harus menggunakan keduanya, dan dokumentasi itu tidak benar-benar menunjukkan saya untuk berpikir ke arah itu. : D

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

public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return cellSpacing
}
Boris
sumber
2

Saya menggunakan monotouch, jadi nama dan kode akan sedikit berbeda, tetapi Anda dapat melakukan ini dengan memastikan bahwa lebar kumpulan koleksi sama dengan (x * lebar sel) + (x-1) * Ruang Minimum dengan x = jumlah sel per baris.

Lakukan saja langkah-langkah berikut berdasarkan pada MinimumInteritemSpacing Anda dan Lebar Sel

1) Kami menghitung jumlah item per baris berdasarkan ukuran sel + inset saat ini + jarak minimum

float currentTotalWidth = CollectionView.Frame.Width - Layout.SectionInset.Left - Layout.SectionInset.Right (Layout = flowlayout)
int amountOfCellsPerRow = (currentTotalWidth + MinimumSpacing) / (cell width + MinimumSpacing)

2) Sekarang Anda memiliki semua info untuk menghitung lebar yang diharapkan untuk tampilan koleksi

float totalWidth =(amountOfCellsPerRow * cell width) + (amountOfCellsPerRow-1) * MinimumSpacing

3) Jadi perbedaan antara lebar saat ini dan lebar yang diharapkan adalah

float difference = currentTotalWidth - totalWidth;

4) Sekarang sesuaikan insets (dalam contoh ini kita menambahkannya ke kanan, sehingga posisi kiri dari koleksi koleksi tetap sama

Layout.SectionInset.Right = Layout.SectionInset.Right + difference;
Mat
sumber
2

Saya memiliki horisontal UICollectionViewdan subkelas UICollectionViewFlowLayout. Tampilan koleksi memiliki sel besar, dan hanya menampilkan satu baris pada satu waktu, dan tampilan koleksi sesuai dengan lebar layar.

Saya mencoba jawaban iago849 dan berhasil, tetapi kemudian saya tahu bahwa saya bahkan tidak memerlukan jawabannya. Untuk beberapa alasan, pengaturan minimumInterItemSpacingtidak melakukan apa-apa. Jarak antara item / sel saya dapat sepenuhnya dikendalikan oleh minimumLineSpacing.

Tidak yakin mengapa ini bekerja seperti ini, tetapi berhasil.

pengguna3344977
sumber
1
ini tampaknya benar - anehnya nilai "garis" sebenarnya adalah pemisah antara item dalam kasus tata letak horizontal.
Fattie
Hey @ user3344977 - temukan bagus Saya memutuskan untuk memisahkan masalah ini menjadi pertanyaan terpisah yang secara langsung membahas tampilan koleksi gulir horizontal sehingga akan lebih mudah ditemukan bagi sebagian orang. Saya merujuk jawaban Anda di sana. Pertanyaan saya ada di sini: stackoverflow.com/q/61774415/826946
Andy Weinstein
1

Saya menemukan masalah serupa dengan OP. Sayangnya jawaban yang diterima tidak berfungsi untuk saya karena konten collectionViewtidak akan terpusat dengan benar. Oleh karena itu saya datang dengan solusi yang berbeda yang hanya mensyaratkan bahwa semua item dalam collectionViewadalah dari lebar yang sama , yang tampaknya menjadi kasus dalam pertanyaan:

#define cellSize 90

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
    float width = collectionView.frame.size.width;
    float spacing = [self collectionView:collectionView layout:collectionViewLayout minimumInteritemSpacingForSectionAtIndex:section];
    int numberOfCells = (width + spacing) / (cellSize + spacing);
    int inset = (width + spacing - numberOfCells * (cellSize + spacing) ) / 2;

    return UIEdgeInsetsMake(0, inset, 0, inset);
}

Kode itu akan memastikan bahwa nilai yang dikembalikan oleh ...minimumInteritemSpacing...akan menjadi jarak yang tepat antara setiap collectionViewCelldan selanjutnya menjamin bahwa sel-sel bersama-sama akan dipusatkan dicollectionView

luk2302
sumber
Itu keren sekali. Tapi saya bertanya-tanya apakah solusi serupa dapat diterapkan untuk jarak vertikal antara elemen
p0lAris
Penspasian vertikal jika Anda memiliki pengguliran horizontal?
luk2302
1

The atas solusi oleh Vojtech-vrbka sudah benar, tetapi itu memicu peringatan:

peringatan: UICollectionViewFlowLayout telah men-cache bingkai ketidakcocokan untuk jalur indeks - nilai cache: Ini kemungkinan terjadi karena tata letak aliran Tata Letak subkelas memodifikasi atribut yang dikembalikan oleh UICollectionViewFlowLayout tanpa menyalinnya

Kode berikut harus memperbaikinya:

class CustomViewFlowLayout : UICollectionViewFlowLayout {

   let cellSpacing:CGFloat = 4

   override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
       let original = super.layoutAttributesForElementsInRect(rect)

       if let original = original {
           let attributes = NSArray.init(array: original, copyItems: true) as! [UICollectionViewLayoutAttributes]

           for (index, attribute) in attributes.enumerate() {
                if index == 0 { continue }
                let prevLayoutAttributes = attributes[index - 1]
                let origin = CGRectGetMaxX(prevLayoutAttributes.frame)
                if(origin + cellSpacing + attribute.frame.size.width < self.collectionViewContentSize().width) {
                    attribute.frame.origin.x = origin + cellSpacing
                }
            }
            return attributes
       }
       return nil
   }
}
Torrao
sumber
2
Seperti jawaban lain pada SO yang menggunakan pendekatan ini, ini tidak berfungsi untuk memasang sel di seluruh lebar kumpulanView, tetapi kesenjangan berselang-seling variabel masih tetap di antara baris. Ini mungkin merupakan batasan dari cara yang sebenarnya dibuat oleh CollectionView.
Womble
1

Versi Swift 3

Cukup buat subclass UICollectionViewFlowLayout dan rekatkan metode ini.

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard let answer = super.layoutAttributesForElements(in: rect) else { return nil }

        for i in 1..<answer.count {
            let currentAttributes = answer[i]
            let previousAttributes = answer[i - 1]

            let maximumSpacing: CGFloat = 8
            let origin = previousAttributes.frame.maxX

            if (origin + maximumSpacing + currentAttributes.frame.size.width < self.collectionViewContentSize.width && currentAttributes.frame.origin.x > previousAttributes.frame.origin.x) {
                var frame = currentAttributes.frame
                frame.origin.x = origin + maximumSpacing
                currentAttributes.frame = frame
            }
        }

        return answer
}
topLayoutGuide
sumber
Ini berfungsi untuk pemasangan horizontal, tetapi celah akan tetap di antara baris, bahkan jika minimumLineSpacingForSectionAt diatur untuk mengembalikan 0, dan layout.minimumLineSpacing diatur ke 0. Juga, sentuhan dalam collectionView akan menyebabkan crash aplikasi, karena loop pertama sedang keluar, kisaran.
Womble
1

Saya sudah mencoba jawaban iago849 dan berhasil.

Cepat 4

open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    guard let answer = super.layoutAttributesForElements(in: rect) else {
        return nil
    }
    let count = answer.count
    for i in 1..<count {
        let currentLayoutAttributes = answer[i]
        let prevLayoutAttributes = answer[i-1]
        let origin = prevLayoutAttributes.frame.maxX
        if (origin + CGFloat(spacing) + currentLayoutAttributes.frame.size.width) < self.collectionViewContentSize.width && currentLayoutAttributes.frame.origin.x > prevLayoutAttributes.frame.origin.x {
            var frame = currentLayoutAttributes.frame
            frame.origin.x = origin + CGFloat(spacing)
            currentLayoutAttributes.frame = frame
        }
    }
    return answer
}

Inilah tautan untuk proyek github. https://github.com/vishalwaka/MultiTags

vishalwaka
sumber
0

Versi sebelumnya tidak benar-benar berfungsi dengan bagian> 1. Jadi solusi saya ditemukan di sini https://codentrick.com/create-a-tag-flow-layout-with-uicollectionview/ . Untuk yang malas:

override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
    let attributesForElementsInRect = super.layoutAttributesForElements(in: rect)
    var newAttributesForElementsInRect = [UICollectionViewLayoutAttributes]()
    // use a value to keep track of left margin
    var leftMargin: CGFloat = 0.0;
    for attributes in attributesForElementsInRect! {
        let refAttributes = attributes 
        // assign value if next row
        if (refAttributes.frame.origin.x == self.sectionInset.left) {
            leftMargin = self.sectionInset.left
        } else {
            // set x position of attributes to current margin
            var newLeftAlignedFrame = refAttributes.frame
            newLeftAlignedFrame.origin.x = leftMargin
            refAttributes.frame = newLeftAlignedFrame
        }
        // calculate new value for current margin
        leftMargin += refAttributes.frame.size.width + 10
        newAttributesForElementsInRect.append(refAttributes)
    }

    return newAttributesForElementsInRect
}
Mantas Laurinavičius
sumber
0

Saya memiliki masalah dengan jawaban yang diterima, jadi saya memperbaruinya, ini berfungsi untuk saya:

.h

@interface MaxSpacingCollectionViewFlowLayout : UICollectionViewFlowLayout
@property (nonatomic,assign) CGFloat maxCellSpacing;
@end

.m

@implementation MaxSpacingCollectionViewFlowLayout

- (NSArray *) layoutAttributesForElementsInRect:(CGRect)rect {
    NSArray *attributes = [super layoutAttributesForElementsInRect:rect];

    if (attributes.count <= 0) return attributes;

    CGFloat firstCellOriginX = ((UICollectionViewLayoutAttributes *)attributes[0]).frame.origin.x;

    for(int i = 1; i < attributes.count; i++) {
        UICollectionViewLayoutAttributes *currentLayoutAttributes = attributes[i];
        if (currentLayoutAttributes.frame.origin.x == firstCellOriginX) { // The first cell of a new row
            continue;
        }

        UICollectionViewLayoutAttributes *prevLayoutAttributes = attributes[i - 1];
        CGFloat prevOriginMaxX = CGRectGetMaxX(prevLayoutAttributes.frame);
        if ((currentLayoutAttributes.frame.origin.x - prevOriginMaxX) > self.maxCellSpacing) {
            CGRect frame = currentLayoutAttributes.frame;
            frame.origin.x = prevOriginMaxX + self.maxCellSpacing;
            currentLayoutAttributes.frame = frame;
        }
    }
    return attributes;
}

@end
Yun CHEN
sumber
0

Solusi saya dalam Swift 3spasi garis sel seperti di Instagram:

masukkan deskripsi gambar di sini

lazy var collectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
    cv.backgroundColor = UIColor.rgb(red: 227, green: 227, blue: 227)
    cv.showsVerticalScrollIndicator = false
    layout.scrollDirection = .vertical
    layout.minimumLineSpacing = 1
    layout.minimumInteritemSpacing = 1
    return cv
}()

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

    switch UIDevice.current.modelName {
    case "iPhone 4":
        return CGSize(width: 106, height: 106)
    case "iPhone 5":
        return CGSize(width: 106, height: 106)
    case "iPhone 6,7":
        return CGSize(width: 124, height: 124)
    case "iPhone Plus":
        return CGSize(width: 137, height: 137)
    default:
        return CGSize(width: frame.width / 3, height: frame.width / 3)
    }
}

Cara mendeteksi perangkat terprogram: https://stackoverflow.com/a/26962452/6013170

Zhanserik
sumber
0

Nah, jika Anda membuat tampilan kumpulan horizontal maka untuk memberi ruang di antara sel, Anda perlu mengatur properti minimumLineSpacing.

Shanu Singh
sumber
-1

Cobalah bermain-main dengan metode ini:

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
                    layout:(UICollectionViewLayout*)collectionViewLayout
    insetForSectionAtIndex:(NSInteger)section {

    UIEdgeInsets insets = UIEdgeInsetsMake(?, ?, ?, ?);

    return insets;
}
Nikola Kirev
sumber
2
Ini hanya berfungsi untuk jarak antar bagian, bukan sel
Diego A. Rincon