UICollectionView içinde hücre aralığı


198

Bir bölümünde hücre aralığını nasıl ayarlayabilirim UICollectionView? Ben minimumInteritemSpacing5.0 için ayarladığım bir özellik olduğunu biliyorum hala aralık 5.0 görünmüyor. Akış delege yöntemini uyguladım.

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

    return 5.0;
}

yine de istenen sonucu alamıyorum. Bence minimum boşluk. Maksimum aralığı ayarlamamın bir yolu yok mu?

simülatör sc


u temsilci yöntemi girip girmediğini kontrol ettiniz mi? kesme noktası koyarak ..
Prashant Nikam

evet delege giriyor, IB de ben de min hücre aralığını 5 olarak ayarladım. Ama ben asgari boşluk sadece hücreler arasında minimum boşluk 5 olması gerekir emin olacak gibi bana yardımcı olacak özellik olduğunu sanmıyorum, ama koleksiyon görünümünde fazladan alan varsa, bu fazladan alanı kullanır. Maksimum hücre aralığı gibi bir şey olmalı
Vishal Singh

Aynı problemim var. 5px çalışmıyor gibi görünüyor. İlginç bir şekilde bunu bir UITableView ile yapabilirsiniz, ancak bir UICollectionView ile yapamaz ...
jerik

Bazı hesaplamalar yaparak düzelttim ... yarın gönderirim. :)
Vishal Singh

2016 İÇİN NOT bu kadar kolay: stackoverflow.com/a/28327193/294884
Fattie

Yanıtlar:


144

Konunun eski olduğunu biliyorum, ancak herkesin hala doğru cevaba ihtiyacı olması durumunda ihtiyacınız olan şey:

  1. Standart akış düzenini geçersiz kıl.
  2. Bunun gibi bir uygulama ekleyin:

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

maximumSpacing istediğiniz herhangi bir değere ayarlanabilir. Bu hile, hücreler arasındaki boşluğun TAMAMEN maksimum Boşluğa eşit olacağını garanti eder !!


Peki, bunu nereye koyacağız?
Jonny

1
Hey Jonny, standart Akış Düzeni'nden miras alın ve bu yöntemi kopyalayıp sınıfınıza yapıştırın.
iago849

1
Aşağıdakileri yapmanız gerekmediğini unutmayın mutableCopy: dizinin içeriğini değiştirmiyorsunuz, ancak içindeki nesneleri değiştiriyorsunuz.
Brock Boland

5
belki yanlış bir şey yapıyorum ya da bu fikir% 100 çalışmıyor, çünkü sonuna kadar
kaydırdığımda

2
Harika gönderi. Bazı durumlarda mizanpajın son satırının biçimlendirmesini bozan bir hatayla karşılaştım. Çözmek için değiştirdim ifVE ek bir koşul: if(origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize.width && currentLayoutAttributes.frame.origin.x > prevLayoutAttributes.frame.origin.x) {
chrisoneiota

190

İlk soruyu destekleme. Üzerinde 5px için aralık almaya çalıştım UICollectionViewama bu çalışmaz, aynı zamanda bir UIEdgeInsetsMake(0,0,0,0)...

Bir UITableView üzerinde bunu doğrudan üst üste x, y koordinatlarını belirterek yapabilirim ...

resim açıklamasını buraya girin

Heres benim UICollectionView kodu:

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

Güncelleme: Sorunumu şu kodla çözdü.

resim açıklamasını buraya girin

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

Bu çok daha iyi bir cevap. UICollectionViewDelegateFlowLayout'ta ayarlayabileceğiniz geri aramalara bir göz atın ve bunun nasıl ayarlanabileceğini görebilirsiniz.
cynistersix

1
Bu yalnızca öğe + aralığı genişliği uicollectionview genişliğine eşit olduğunda işe yarayacağını düşünüyorum.
xi.lin

@JayprakashDubey şu anda hızlı uyum yok. Denemelisin. İyi şanslar
jerik

5 piksellik hücreler arasındaki genişliği nerede belirtiyorsunuz?
UKDataGeek

1
Kabul edilen yanıttan çok daha iyi bir cevap, çünkü UICollectionViewLayout sadece bir yöntemi geçersiz kılmak için alt sınıflandırma aşırıya kaçma gibi görünüyor ve geçersiz kılınması gereken diğer tüm yöntemler göz önüne alındığında önemsiz bir mesele değil.
Cindeselia

80

Yatay bir akış düzeni kullanarak, hücreler arasında 10 puan boşluk bırakıyordum. Ben ayarlamak için gerekli aralık kaldırmak için minimumLineSpacinghem de minimumInterItemSpacingsıfıra.

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

Ayrıca, tüm hücreleriniz aynı boyuttaysa, özelliği temsilci yöntemlerini kullanmak yerine doğrudan akış düzeninde ayarlamak daha basit ve daha verimlidir.


34
Şaşırtıcı bir şekilde, minimumLineSpacing hücreler arasındaki yatay boşluğu etkiler.
Matt H

4
ME de, hücreler arasında yatay bir kaydırma ve sıfır boşluk gerekir ve minimumLineSpacing = 0 anahtarıdır.
Wingzero

3
Bu etkiyi elde edebildi olmadan kullanarak minimumInteritemSpacing. Sadece minimumLineSpacing = 0yatay düzenimi ayarlamak öğeler arasındaki yatay boşluğu kaldırdı.
Ziewvater

1
Bunu düşünürseniz, öğeler arasındaki yatay mesafe, yatay olarak akan bir düzen için satır aralığıdır. Satır aralığı, tipik, dikey olarak akan bir mizanpajdaki öğeler arasındaki dikey mesafedir.
lancejabr

62

Unutmayın, minimum satır aralığıdır , minimum öğe arası boşluk veya hücre alanı değildir. Çünkü collectionView öğenizin kaydırma yönü YATAYDIR .

Dikey ise, hücreler arasındaki yatay boşluk için hücre boşluğunu veya öğeler arası boşluğu ve hücreler arasındaki dikey boşluk için satır aralığını ayarlamanız gerekir.

Objective-C sürümü

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

Hızlı sürüm:

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

şimdi 0 döndüğümde alt boşluk gitti; sağ taraftaki alan nasıl kaldırılır?
Bangalore

Hey, sorunuzu çok iyi anlamadım. Ama insetForSectionAtIndex aradığınız şey bu. - (UIEdgeInsets) collectionView: (UICollectionView *) collectionView düzen: (UICollectionViewLayout *) collectionViewLayout insetForSectionAtIndex: (NSInteger) bölümü {return UIEdgeInsetsMake (5, 10, 5, 10); }
Vincent Joy

Hem yatay hem de dikey için minimum satır aralığıdır.
Swati

Günümü kurtardın (Y).
Umair_UAS

Ah benim kelime! Buna inanamıyorum. Teşekkürler
Magoo

36

Her öğe arasında 5 piksel boşluk olduğundan emin olmak için bu kodu deneyin:

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

Lütfen kodunuzu kod bloğu olarak biçimlendirin, böylece SO'da güzel görünecektir.
Boru

33

Swift En popüler cevabın sürümü. Hücreler arasındaki boşluk eşit olacaktır 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
    }
}

super.layoutAttributesForElements (in: rect) herhangi bir fikre geri dönüyor mu?
Ashok R

Bunu kullanan diğer tüm yöntemler gibi, bu da birden çok satır için düzgün çalışmaz. Aralıklı, yuvarlama hatası tarzı boşluklar, uygun temsilci yöntemleri ve 0 kullanmak üzere ayarlanmış özellikler olsa bile, satırlar arasında kalacaktır. Bu bir UICollectionView oluşturma sorunu olabilir.
Womble

30

IB kullanarak hücreler veya satırlar arasındaki boşluğu yapılandırmanın çok kolay bir yolunu buldum.

Film şeridi / Xib dosyasından UICollectionView'u seçin ve aşağıdaki resimde belirtildiği gibi Boyut Denetimi'ne tıklayın .

resim açıklamasını buraya girin

Alanı programlı olarak yapılandırmak için aşağıdaki özellikleri kullanın.

1) Satırlar arasındaki boşluğu ayarlamak için.

[self.collectionView setMinimumLineSpacing:5];

2) Öğeler / hücreler arasındaki boşluğu ayarlamak için.

[self.collectionView setMinimumInteritemSpacing:5];

1
Bu, her zaman belirtilen değerden ziyade, belirtilen değerden daha büyük olacak minimum alan.
Vishal Singh

21

Lütfen minimumInterItemSpacing özellik adını not edin . Bu , tam aralık değil, öğeler arasındaki minimum boşluk olacaktır . MinimumInterItemSpacing öğesini bir değere ayarlarsanız, boşluk bırakmanın bundan daha düşük bir değer olmayacağından emin olabilirsiniz. Ancak daha yüksek bir değer elde etme şansı vardır.

Aslında öğeler arasındaki boşluk itemSize ve sectionInset gibi çeşitli faktörlere bağlıdır . Koleksiyon görünümü, içeriği bu değerlere göre dinamik olarak yerleştirir. Böylece tam aralığı garanti edemezsiniz. SectionInset ve minimumInterItemSpacing ile deneme yanılma yapmanız gerekir .


1
@Anil kenar böcekler? : D
NightFury

10
Bölümünüzde böcekler olabilir.
Nestor

24
insect == böcek && insect! = inset :)
Nestor

16

Swift 3.0, Xcode 8 için cevap

1. toplama görünümü temsilci ayarladığınızdan emin olun

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

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

2.Implement UICollectionViewDelegateFlowLayout protokol değil, 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
    }
}

1
Orada halkı kaldırabileceğinizi düşünün. İyi çalışmalı ve diğer tüm işlevlerle uyumlu olmalıdır.
Edward Potter

Bu dikey kaydırma koleksiyonu görünümü için işe yarar mı? İPhone 6s ve 6s Plus gibi cihazlarda yatay olarak 2 hücre göstermesi gereken koleksiyon görünümüne sahibim, ancak 5s, 5 ve SE'den daha düşük bir şey için sadece bir hücre göstermelidir. Mevcut kodum çalışıyor ancak 6s Plus cihazında hücreler arasındaki boşluk çok fazla ve çirkin görünüyor ve bu boşluğu azaltmaya çalışıyorum ve bu, diğer tüm cihazlar tasarımım gereği çalıştığı için tek gereklilik.
AnBisw

11

Boşluk için basit kod

let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.minimumInteritemSpacing = 10 // Some float value

3
Yatay hücre aralığı için kullanmalısınız: minimumLineSpacing
Alfi

9

Cevabı olarak (ve ayrıca hızlı versiyonu ) küçük sorunu var: Sağdaki büyük boşluk olacaktır.

Bunun nedeni, akış düzeninin hücre boşluğunu tam olarak, kayan bir sol davranışla yapacak şekilde özelleştirilmesidir .

Benim çözümüm bölüm iç kısmını manipüle etmektir, böylece bölüm merkeze hizalanır, ancak boşluk tam olarak belirtildiği gibidir.

Aşağıdaki ekran görüntüsünde, öğe / satır aralığı tam olarak 8pt, sol ve sağ ek bölüm 8pt'den daha büyük olacaktır (merkeze hizalamak için):

eşit aralıklı hücreler

Swift kodu şöyle:

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
}

1
Bir 'NSInvalidArgumentException' alıyorum, nedeni: '*** setObjectForKey: nesne nil olamaz (anahtar: <NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0})' yakalanmamış istisna.
DaftWooly

... yanılmıyorsam, while let n = Int((containerWidth + minItemSpacing)/((itemWidth+minItemSpacing)))
döngünüz şuna

Kodu olduğu gibi kullanmadı, ancak bu bana koleksiyon görünümü için dışarı akış düzenimi uygulamak için en iyi referans verdi. şerefe
Dima Gimburg

8

UICollectionViewDelegateFlowLayoutBaşlık dosyanızdaki protokolü tanımlayın .

Aşağıdaki UICollectionViewDelegateFlowLayoutprotokol yöntemini uygulayın :

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

UIEdgeInsetMakeYöntemin Apple Dokümantasyonunu görmek için Buraya tıklayın .


4

Film Şeridi Yaklaşımı

Film şeridinizde CollectionView'u seçin ve boyut denetçisine gidin ve hücreler ve çizgiler için minimum aralığı 5 olarak ayarlayın

Swift 5 Programlı olarak

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

3

U, gerçek hücre boyutuna dokunmadan aralığı değiştirmek istiyorsanız, bu benim için en iyi çözümdür. #xcode 9 # tvOS11 # iOS11 # swift

Yani UICollectionViewDelegateFlowLayout , değiştirmek sonraki yöntemleri uygulamak, hile u her ikisini kullanmak zorunda ve belgeleri gerçekten bu yönde düşünmek beni işaret değildi. : 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
}

2

Monotouch kullanıyorum, bu yüzden adlar ve kod biraz farklı olacak, ancak bunu toplama görünümünün genişliğinin (x * hücre genişliği) + (x-1) * MinimumSpacing x = miktarı ile eşit olduğundan emin olarak yapabilirsiniz satır başına hücre sayısı.

MinimumInteritemSpacing ve Hücrenin Genişliğine göre aşağıdaki adımları uygulamanız yeterlidir

1) Satır başına öğe miktarını hücre boyutuna + mevcut eklere + minimum aralığa göre hesaplıyoruz

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

2) Artık koleksiyon görünümü için beklenen genişliği hesaplamak için tüm bilgilere sahipsiniz

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

3) Böylece mevcut genişlik ve beklenen genişlik arasındaki fark

float difference = currentTotalWidth - totalWidth;

4) Şimdi ekleri ayarlayın (bu örnekte sağa ekliyoruz, böylece toplama görünümünün sol konumu aynı kalıyor

Layout.SectionInset.Right = Layout.SectionInset.Right + difference;

2

Yatay UICollectionViewve alt sınıflarım varUICollectionViewFlowLayout . Koleksiyon görünümü büyük hücrelere sahiptir ve bir seferde yalnızca bir satırı gösterir ve koleksiyon görünümü ekranın genişliğine uyar.

Iago849'un cevabını denedim ve işe yaradı, ama sonra cevabına bile ihtiyacım olmadığını öğrendim. Nedense, ayar yapmak minimumInterItemSpacinghiçbir şey yapmaz. Öğelerim / hücrelerim arasındaki boşluk tamamen tarafından kontrol edilebilir minimumLineSpacing.

Neden bu şekilde çalıştığından emin değilim, ama işe yarıyor.


1
bu doğru gibi görünüyor - garip bir şekilde "satırlar" değeri, aslında, yatay bir düzen durumunda öğeler arasındaki ayırıcıdır.
Fattie

Hey @ user3344977 - güzel bul. Bu sorunu, yatay kaydırma toplama görünümlerini doğrudan ele alan ve bazı insanlar için daha kolay bulunabilmesi için ayrı bir soruya ayırmaya karar verdim. Cevabınızı orada referanslıyorum. Benim sorum burada: stackoverflow.com/q/61774415/826946
Andy Weinstein

1

OP ile benzer bir sorunla karşılaştım. Maalesef kabul edilen cevap benim için işe yaramadı çünkü içeriğinin collectionViewdoğru bir şekilde ortalanmayacağı. Bu nedenle, yalnızca söz konusu collectionViewdurumda olan tüm öğelerin aynı genişlikte olmasını gerektiren farklı bir çözüm buldum :

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

Bu kod, döndürülen değerin ...minimumInteritemSpacing...her biri arasındaki tam aralık olmasını sağlar collectionViewCellve ayrıca hücrelerin hep birliktecollectionView


Bu oldukça havalı. Ancak benzer bir çözümün öğeler arasındaki dikey boşluğa uygulanıp uygulanamayacağını merak ediyordum
p0lAris

Yatay kaydırmanız durumunda dikey boşluk?
luk2302

1

Yukarıdaki çözelti ile Vojtech-Vrbka doğru ancak bir uyarı tetikler:

uyarı: UICollectionViewFlowLayout, dizin yolu için önbelleğe alınan değer için çerçeve uyumsuzluğunu önbelleğe aldı: Bu, büyük olasılıkla, akış düzeni alt sınıfı Düzeni, UICollectionViewFlowLayout tarafından kopyalanmadan döndürülen öznitelikleri değiştirdiği için gerçekleşiyor

Aşağıdaki kod düzeltmelidir:

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

2
Bu yaklaşımı kullanan SO'daki diğer cevaplar gibi, bu da hücreleri collectionView genişliği boyunca takmak için işe yarar, ancak satırlar arasında aralıklı, değişken yükseklik boşlukları hala kalır. Bu, CollectionView'ın gerçekte yaratma biçiminin bir sınırlaması olabilir.
Womble

1

Swift 3 Sürümü

Sadece bir UICollectionViewFlowLayout alt sınıfı oluşturun ve bu yöntemi yapıştırın.

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
}

Bu yatay montaj için çalışır, ancak minimumLineSpacingForSectionAt 0 döndürecek şekilde ayarlanmış ve layout.minimumLineSpacing 0 olarak ayarlanmış olsa bile, satırlar arasında boşluklar kalır. aralığı.
Womble

1

İago849'un cevabını denedim ve işe yaradı.

Hızlı 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
}

İşte github projesi için link. https://github.com/vishalwaka/MultiTags


0

Önceki sürümler bölümler> 1 ile gerçekten çalışmadı. Bu yüzden çözümüm burada bulundu https://codentrick.com/create-a-tag-flow-layout-with-uicollectionview/ . Tembel olanlar için:

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
}

0

Kabul edilen cevapla ilgili bir sorunum var, bu yüzden güncelledim, bu benim için çalışıyor:

.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

0

Swift 3Instagram'daki gibi hücre hattı boşluklarındaki çözümüm :

resim açıklamasını buraya girin

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

Cihaz programlı olarak nasıl algılanır: https://stackoverflow.com/a/26962452/6013170


0

Yatay bir koleksiyon görünümü oluşturuyorsanız, hücreler arasında boşluk bırakmak için özelliği ayarlamanız gerekir minimumLineSpacing.


-1

Bu yöntemle oynamayı deneyin:

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

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

    return insets;
}

2
Bu sadece bölümler arasındaki boşluk için çalışır, hücreler için değil
Diego A. Rincon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.