Міжрядковий інтервал в UICollectionView


197

Як встановити інтервал між клітинками в розділі UICollectionView? Я знаю, що є властивість, яку minimumInteritemSpacingя встановив на 5,0, але інтервал не з’являється 5,0. Я реалізував метод делегування потоку.

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

    return 5.0;
}

все-таки я не отримую бажаного результату. Я думаю, що це мінімальний інтервал. Чи не існує способу встановити максимальний інтервал?

тренажер sc


Ви перевірили, чи вводиться це метод делегата чи ні ..? поставивши точку розриву ..
Прашант Нікам

так, це введення делегата, в IB я також встановив мінімальний проміжок клітинки на 5. Але я не думаю, що мінімальний простір - це властивість, яка допоможе мені, оскільки це просто переконається, що мінімальний простір між клітинками повинен бути 5, але якщо у представлення колекції є додатковий простір, він буде використовувати цей додатковий простір. Має бути щось на кшталт максимального інтервалу в клітинках
Вішал Сінгх,

У мене така ж проблема. Здається, 5px не працює. Цікаво я можу це зробити з UITableView, але не з UICollectionView ...
jerik

Я зафіксував це, роблячи деякі підрахунки .. Я опублікую це завтра. :)
Vishal Singh

ПРИМІТКА. Для 2016 року це дуже просто: stackoverflow.com/a/28327193/294884
Fattie

Відповіді:


145

Я знаю, що ця тема стара, але у випадку, якщо хтось все-таки потребує правильної відповіді, що вам потрібно:

  1. Заміна стандартної схеми потоку.
  2. Додайте подібну реалізацію:

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

де maxSpacing може бути встановлений на будь-яке значення, яке ви віддаєте перевагу. Цей трюк гарантує, що простір між клітинками буде ТОЧНО рівним maxSpacing !!


Отже, куди ми це покладемо?
Джонні

1
Ей, Джоні, успадкуй від стандартної схеми потоку та просто скопіюй та вставивши цей метод у свій клас.
iago849

1
Зауважте, що вам не потрібно робити mutableCopy: ви не мутуєте вміст масиву, а мутуєте об'єкти в ньому.
Брок Боланд

5
можливо я роблю щось не так, або ця ідея не працює на 100%, тому що, коли я прокручую до кінця, я бачу, що деякі клітини накладаються один на одного :(
pash3r

2
Чудовий пост. Я зіткнувся з помилкою, яка порушила форматування останнього рядка макета за певних обставин. Щоб вирішити, я змінив ifна І додаткову умову: if(origin + maximumSpacing + currentLayoutAttributes.frame.size.width < self.collectionViewContentSize.width && currentLayoutAttributes.frame.origin.x > prevLayoutAttributes.frame.origin.x) {
chrisoneiota

190

Підтримка початкового питання. Я спробував отримати відстань до 5 пікселів на, UICollectionViewале це не працює, як і з UIEdgeInsetsMake(0,0,0,0)...

У UITableView я можу це зробити, безпосередньо вказавши координати x, y підряд ...

введіть тут опис зображення

Ось мій код UICollectionView:

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

Оновлення: вирішено мою проблему із наступним кодом.

введіть тут опис зображення

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

Це набагато краща відповідь. Погляньте на зворотні дзвінки, які можна налаштувати в UICollectionViewDelegateFlowLayout, і ви можете побачити, як це можна змінити.
cynistersix

1
Я думаю, це може працювати лише тоді, коли ширина елемента + інтервал дорівнює ширині перегляду uicollection.
xi.lin

@JayprakashDubey на даний момент я не підходить швидко. Ви повинні спробувати. Удачі
jerik

Де ви вказуєте ширину між клітинками 5 пікселів?
UKDataGeek

1
Набагато краща відповідь, ніж прийнята, головним чином тому, що підкласифікація UICollectionViewLayout лише для переосмислення одного методу здається надмірною, і це не є тривіальною справою, враховуючи всі інші методи, які потрібно скасувати.
Cindeselia

80

Використовуючи горизонтальну схему потоку, я також отримував 10 очок між клітинками. Для видалення інтервалу мені потрібно було встановити minimumLineSpacingтак само, як minimumInterItemSpacingі нуль.

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

Крім того, якщо всі ваші клітини однакового розміру, простіше і ефективніше встановити властивість на макеті потоку безпосередньо замість використання методів делегування.


34
Дивно, але minimalLineSpacing впливає на горизонтальний простір між клітинками.
Метт H

4
Я також потребую горизонтальної прокрутки та нульового проміжку між клітинками, а мінімальнийLineSpacing = 0 є ключовим.
Wingzero

3
Мені вдалося отримати цей ефект без використання minimumInteritemSpacing. Щойно встановлення minimumLineSpacing = 0на моєму горизонтальному макеті видалило горизонтальний проміжок між елементами.
Ziewvater

1
Якщо ви задумаєтесь, горизонтальна відстань між елементами - це проміжок між рядками для горизонтально протікаючого макета. Міжрядковий інтервал - це вертикальна відстань між елементами в типовому вертикально-проточному макеті.
lancejabr

62

Пам'ятайте, що це мінімальний простір рядка , а не мінімальний інтервал між елементами або простір комірки. Оскільки напрямок прокрутки вашої колекціїView HORIZONTAL .

Якщо вона вертикальна, то вам потрібно встановити простір комірок або міжрядковий простір для горизонтального простору між комірками та міжрядкового інтервалу для вертикального простору між комірками.

Версія Objective-C

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

Швидка версія:

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

тепер пробіл внизу, коли я повертаю 0; як видалити простір з правого боку?
Бангалор

Гей, я не дуже добре зрозумів ваше запитання. Але я думаю, що insetForSectionAtIndex - це те, що ви шукаєте. - (UIEdgeInsets) collectionView: (UICollectionView *) макет collectionView: (UICollectionViewLayout *) collectionViewLayout insetForSectionAtIndex: (NSInteger) розділ {повернути UIEdgeInsetsMake (5, 10, 5, 10); }
Вінсент Джой

Це мінімальний міжрядковий інтервал для горизонтальних і вертикальних.
Swati

Ти врятував мій день (Y).
Umair_UAS

О, моє слово! Я не можу повірити в це. Спасибі
Magoo

36

Спробуйте скористатися цим кодом, щоб переконатися, що між кожним елементом є відстань 5 пікселів:

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

Будь ласка, відформатуйте свій код у вигляді кодового блоку, щоб він добре відображався на SO.
Проводити

33

Швидка версія найпопулярнішої відповіді. Простір між клітинками буде дорівнює 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 (в: rect) повертає нуль будь-яку ідею?
Ашок R

Як і всі інші методи, які використовують це, це не працює належним чином для кількох рядків. Переривчасті прогалини в стилі округлення залишатимуться між рядками, навіть якщо відповідні методи делегації та властивості встановлені для використання 0. Це може бути проблемою візуалізації UICollectionView.
Womble

30

Я знайшов дуже простий спосіб налаштувати проміжки між клітинками або рядками за допомогою ІБ.

Просто виберіть UICollectionView з файлу розкадрування / Xib та натисніть на Розмір Інспектор, як зазначено нижче на зображенні.

введіть тут опис зображення

Для налаштування простору програмно використовуйте наступні властивості.

1) Для встановлення місця між рядками.

[self.collectionView setMinimumLineSpacing:5];

2) Для встановлення місця між елементами / клітинками.

[self.collectionView setMinimumInteritemSpacing:5];

1
Та мінімальний простір, який буде більшим за вказане значення і не завжди вказане значення.
Вішал Сінгх

21

Зверніть увагу на ім'я властивості minimumInterItemSpacing . Це буде мінімальний проміжок між елементами, а не точний інтервал. Якщо встановити minimInterItemSpacing на якесь значення, ви можете запевнити, що пробіл не буде значенням меншим від цього. Але є шанс отримати більшу цінність.

Насправді інтервал між елементами залежить від декількох факторів itemSize та sectionInset . Перегляд колекції динамічно розміщує вміст на основі цих значень. Таким чином, ви не можете забезпечити точний інтервал. Ви повинні зробити деякі спроби та помилки з розділомInset та minimalInterItemSpacing .


1
@Anil край комах? : D
NightFury

10
У вашому розділі Innsects можуть бути помилки.
Нестор

24
insect == bug && insect! = inset :)
Нестор

16

Відповідь на Swift 3.0, Xcode 8

1.Упевніться, що ви встановили делегата перегляду колекції

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

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

2.Виконання протоколу UICollectionViewDelegateFlowLayout , а не 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
Подумайте, ви можете видалити там публіку. Має працювати нормально та відповідати всім іншим функціям.
Едвард Поттер

Чи це може працювати для перегляду колекції вертикальної прокрутки? Я маю представлення колекції, де воно повинно відображати 2 комірки по горизонталі на таких пристроях, як iPhone 6s і 6s Plus, але повинно показувати лише одну клітинку для нічого нижчого, ніж 5s, 5 та SE. Мій поточний код працює, але в пристрої 6s Plus розрив між клітинками занадто великий і виглядає некрасивим, і я намагаюся зменшити цей розрив, і це єдина вимога, оскільки всі інші пристрої працюють відповідно до моєї конструкції.
AnBisw

11

Простий код для інтервалу

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

3
Для горизонтального інтервалу клітинок слід використовувати: minimalLineSpacing
Alfi

9

Проголосували відповідь (а також версія скор ) є невелике питання: буде великий інтервал праворуч.

Це пояснюється тим, що схема потоку налаштована таким чином, щоб зробити інтервал комірок точним, з поворотом лівої поведінки.

Моє рішення полягає в тому, щоб маніпулювати вставкою секції, щоб секція була вирівняною по центру, але інтервал точно такий, як зазначено.

На знімку екрана нижче інтервал між елементами та рядками рівно 8pt, тоді як лівий та правий вставки розділу будуть більшими за 8pt (щоб вирівняти його по центру):

рівномірно розташовані клітини

Код Swift як такий:

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
Я отримую 'NSInvalidArgumentException', причина: '*** setObjectForKey: об'єкт не може бути нульовим (ключ: <NSIndexPath: 0xc000000000000016> {length = 2, path = 0 - 0})' uncaught виключення.
DaftWooly

... якщо я не помиляюся, ваш цикл while прирівнюється до: let n = Int((containerWidth + minItemSpacing)/((itemWidth+minItemSpacing)))
DaftWooly

Не використовував код таким, який є, але це дало мені найкращу орієнтацію для реалізації моєї схеми вихідного потоку для подання колекції. ура
Діма Гімбург

8

Визначте UICollectionViewDelegateFlowLayoutпротокол у файлі заголовка.

Реалізуйте такий UICollectionViewDelegateFlowLayoutпротокол, як цей:

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

Клацніть тут, щоб побачити Документацію Apple про UIEdgeInsetMakeметод.


3

Якщо ви хочете налаштувати інтервал, не торкаючись фактичного розміру комірки, це рішення, яке найкраще працювало для мене. #xcode 9 # tvOS11 # iOS11 #swift

Тож у UICollectionViewDelegateFlowLayout змініть реалізацію наступних методів, фокус у тому, що ви повинні використовувати обидва, і документація насправді не вказує мені думати в цьому напрямку. : 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
}

3

Підхід до розгортки

Виберіть CollectionView у вашій дошці та перейдіть до інспектора розміру та встановіть мінімальну відстань для комірок та рядків як 5

Swift 5 програмно

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

2

Я використовую monotouch, тому імена та код будуть дещо різними, але ви можете це зробити, переконавшись, що ширина колекції перегляду дорівнює (x * ширина комірки) + (x-1) * MinimumSpacing з x = сума комірок в ряд.

Просто виконайте наступні дії, засновані на вашому MinimumInteritemSpacing та ширині комірки

1) Ми обчислюємо кількість елементів у рядку, виходячи з розміру комірки + поточні вставки + мінімальний інтервал

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

2) Тепер у вас є вся інформація для розрахунку очікуваної ширини для подання колекції

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

3) Отже, різниця між поточною шириною та очікуваною шириною є

float difference = currentTotalWidth - totalWidth;

4) Тепер відрегулюйте вставки (у цьому прикладі ми додаємо його праворуч, так що ліве положення колекції перегляду залишається таким же

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

2

У мене горизонтальний UICollectionViewі підкласичний UICollectionViewFlowLayout. У вікні колекції є великі клітинки і відображається одночасно лише один їх ряд, а представлення колекції відповідає ширині екрана.

Я спробував відповідь iago849, і це спрацювало, але потім я з’ясував, що навіть мені не потрібна його відповідь. Чомусь встановлення minimumInterItemSpacingзначень нічого не робить. Відстань між моїми предметами / клітинками може повністю контролюватися minimumLineSpacing.

Не впевнений, чому це працює так, але він працює.


1
це здається правдою - як не дивно, значення "рядків" насправді є роздільником між елементами у випадку горизонтального макета.
Fattie

Гей @ user3344977 - приємна знахідка. Я вирішив розділити це питання на окреме запитання, яке безпосередньо стосується горизонтальних переглядів колекції прокрутки, щоб їх було легше знайти. Я посилаюся на вашу відповідь там. Моє запитання тут: stackoverflow.com/q/61774415/826946
Енді Вайнштейн

1

Я натрапив на аналогічну проблему, як ОП. На жаль, прийнята відповідь не спрацювала для мене, оскільки зміст цього пункту collectionViewне був би центрований належним чином. Тому я придумав інше рішення, яке вимагає лише, щоб усі елементи collectionViewбули однакової ширини , що, мабуть, має місце у питанні:

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

Цей код гарантуватиме, що значення, яке повертається, ...minimumInteritemSpacing...буде точним проміжком між усіма, collectionViewCellі, крім того, гарантує, що комірки всі разом будуть зосереджені вcollectionView


Це досить круто. Але мені було цікаво, чи можна застосувати подібне рішення до вертикальних відстаней між елементами
p0lAris

Вертикальний інтервал у випадку, якщо у вас горизонтальна прокрутка?
luk2302

1

Вище рішення по Войтех-Vrbka є правильним , але це викликає попередження:

попередження: UICollectionViewFlowLayout має кешоване невідповідність кадру для показника кешованого шляху: Це, ймовірно, трапляється тому, що макет підкласу макета потоку є зміною атрибутів, повернутих UICollectionViewFlowLayout, не копіюючи їх

Наступний код повинен виправити:

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
Як і інші відповіді на SO, які використовують такий підхід, і це працює для розміщення комірок по ширині collectionView, але переміжні проміжки, що змінюються по висоті, все ще залишаються між рядками. Це може бути обмеженням того, як насправді відображається CollectionView.
Womble

1

Версія Swift 3

Просто створіть підклас UICollectionViewFlowLayout та вставте цей метод.

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
}

Це працює для горизонтальної підгонки, але проміжки залишатимуться між рядками, навіть якщо мінімальнийLineSpacingForSectionAt встановлений для повернення 0, а layout.minimumLineSpacing встановлено у 0. Також, дотик у collectionView приведе до виходу з ладу додатка, оскільки перший цикл буде вимкнений діапазону.
Womble

1

Я спробував відповідь iago849, і він спрацював.

Швидкий 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
}

Ось посилання на проект github. https://github.com/vishalwaka/MultiTags


0

Попередні версії насправді не працювали з розділами> 1. Тому моє рішення було знайдено тут https://codentrick.com/create-a-tag-flow-layout-with-uicollectionview/ . Для ледачих:

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

У мене проблема з прийнятою відповіддю, тому я її оновив, це працює для мене:

.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 3інтервалі між клітинками, як в Instagram:

введіть тут опис зображення

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

Як програмно виявити пристрій: https://stackoverflow.com/a/26962452/6013170


0

Ну а якщо ви створюєте горизонтальний вигляд колекції, то для надання місця між клітинками потрібно встановити властивість minimumLineSpacing.


-1

Спробуйте пограти цим методом:

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

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

    return insets;
}

2
Це працює лише на відстань між секціями, а не на комірки
Дієго А. Рінкон
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.