Как вы определяете расстояние между ячейками в UICollectionView flowLayout

У меня есть UICollectionView с макетом потока, и каждая ячейка представляет собой квадрат. Как определить расстояние между ячейками в каждом ряду? Я не могу найти соответствующие настройки для этого. Я вижу, что в nib-файле есть атрибуты min spacing для представления коллекции, но я установил это значение в 0, и ячейки даже не прилипают.

Любая другая идея?

11 ответов

Решение

Обновление: Swift версия этого ответа: https://github.com/fanpyi/UICollectionViewLeftAlignedLayout-Swift


Взяв на себя инициативу @matt, я изменил его код, чтобы убедиться, что элементы ВСЕГДА выровнены. Я обнаружил, что если бы элемент оказался в отдельной строке, он был бы центрирован по схеме потока. Я сделал следующие изменения для решения этой проблемы.

Такая ситуация может возникнуть, только если у вас есть ячейки, которые различаются по ширине, что может привести к макету, подобному следующему. Последняя строка всегда слева выравнивается из-за поведения UICollectionViewFlowLayoutпроблема заключается в элементах, которые находятся в любой строке, кроме последней.

С кодом @ Мэтта я видел.

В этом примере мы видим, что ячейки центрируются, если они сами оказываются на линии. Код ниже гарантирует, что ваш вид коллекции будет выглядеть следующим образом.

#import "CWDLeftAlignedCollectionViewFlowLayout.h"

const NSInteger kMaxCellSpacing = 9;

@implementation CWDLeftAlignedCollectionViewFlowLayout

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
    NSArray* attributesToReturn = [super layoutAttributesForElementsInRect:rect];
    for (UICollectionViewLayoutAttributes* attributes in attributesToReturn) {
        if (nil == attributes.representedElementKind) {
            NSIndexPath* indexPath = attributes.indexPath;
            attributes.frame = [self layoutAttributesForItemAtIndexPath:indexPath].frame;
        }
    }
    return attributesToReturn;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewLayoutAttributes* currentItemAttributes =
    [super layoutAttributesForItemAtIndexPath:indexPath];

    UIEdgeInsets sectionInset = [(UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout sectionInset];

    if (indexPath.item == 0) { // first item of section
        CGRect frame = currentItemAttributes.frame;
        frame.origin.x = sectionInset.left; // first item of the section should always be left aligned
        currentItemAttributes.frame = frame;

        return currentItemAttributes;
    }

    NSIndexPath* previousIndexPath = [NSIndexPath indexPathForItem:indexPath.item-1 inSection:indexPath.section];
    CGRect previousFrame = [self layoutAttributesForItemAtIndexPath:previousIndexPath].frame;
    CGFloat previousFrameRightPoint = previousFrame.origin.x + previousFrame.size.width + kMaxCellSpacing;

    CGRect currentFrame = currentItemAttributes.frame;
    CGRect strecthedCurrentFrame = CGRectMake(0,
                                              currentFrame.origin.y,
                                              self.collectionView.frame.size.width,
                                              currentFrame.size.height);

    if (!CGRectIntersectsRect(previousFrame, strecthedCurrentFrame)) { // if current item is the first item on the line
        // the approach here is to take the current frame, left align it to the edge of the view
        // then stretch it the width of the collection view, if it intersects with the previous frame then that means it
        // is on the same line, otherwise it is on it's own new line
        CGRect frame = currentItemAttributes.frame;
        frame.origin.x = sectionInset.left; // first item on the line should always be left aligned
        currentItemAttributes.frame = frame;
        return currentItemAttributes;
    }

    CGRect frame = currentItemAttributes.frame;
    frame.origin.x = previousFrameRightPoint;
    currentItemAttributes.frame = frame;
    return currentItemAttributes;
}

@end

Чтобы получить максимальный интервал между элементами, создайте подкласс UICollectionViewFlowLayout и переопределите layoutAttributesForElementsInRect: а также layoutAttributesForItemAtIndexPath:,

Например, общая проблема заключается в следующем: строки представления коллекции выровнены по правому и левому краю, за исключением последней строки, выровненной по левому краю. Допустим, мы хотим, чтобы все линии были выровнены по левому краю, чтобы расстояние между ними составляло, скажем, 10 точек. Вот простой способ (в вашем подклассе UICollectionViewFlowLayout):

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
    NSArray* arr = [super layoutAttributesForElementsInRect:rect];
    for (UICollectionViewLayoutAttributes* atts in arr) {
        if (nil == atts.representedElementKind) {
            NSIndexPath* ip = atts.indexPath;
            atts.frame = [self layoutAttributesForItemAtIndexPath:ip].frame;
        }
    }
    return arr;
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewLayoutAttributes* atts =
    [super layoutAttributesForItemAtIndexPath:indexPath];

    if (indexPath.item == 0) // degenerate case 1, first item of section
        return atts;

    NSIndexPath* ipPrev =
    [NSIndexPath indexPathForItem:indexPath.item-1 inSection:indexPath.section];

    CGRect fPrev = [self layoutAttributesForItemAtIndexPath:ipPrev].frame;
    CGFloat rightPrev = fPrev.origin.x + fPrev.size.width + 10;
    if (atts.frame.origin.x <= rightPrev) // degenerate case 2, first item of line
        return atts;

    CGRect f = atts.frame;
    f.origin.x = rightPrev;
    atts.frame = f;
    return atts;
}

Причина, по которой это так просто, в том, что мы не выполняем тяжелую работу по макету; мы используем макетную работу, которую UICollectionViewFlowLayout уже сделал для нас. Уже определено, сколько предметов идет в каждой строке; мы просто читаем эти строки и собираем все вместе, если вы понимаете, о чем я.

Есть несколько вещей, которые следует учитывать:

  1. Попробуйте изменить минимальный интервал в IB, но оставьте курсор в этом поле. Обратите внимание, что Xcode не сразу помечает документ как измененный. Однако, когда вы щелкаете в другом поле, XCode замечает, что документ изменен, и помечает его в навигаторе файлов. Поэтому обязательно внесите вкладку или нажмите на другое поле после внесения изменений.

  2. Сохраните файл раскадровки /xib после внесения изменений и обязательно перестройте приложение. Нетрудно пропустить этот шаг, и тогда вы остаетесь чесать голову, задаваясь вопросом, почему ваши изменения, похоже, не дали никакого эффекта.

  3. UICollectionViewFlowLayout имеет minimumInteritemSpacing свойство, которое вы устанавливаете в IB. Но у делегата коллекции также может быть метод определения расстояния между элементами. Этот метод имеет преимущество свойства макета, поэтому, если вы реализуете его в своем делегате, свойство вашего макета не будет использовано.

  4. Помните, что расстояние там минимально. Макет будет использовать это число (независимо от того, получено ли оно из свойства или из метода делегата) в качестве наименьшего допустимого пространства, но он может использовать больший пробел, если у него осталось место на строке. Так, если, например, вы установили минимальный интервал в 0, вы все равно можете увидеть несколько пикселей между элементами. Если вам нужен больший контроль над точным расположением элементов, вам, вероятно, следует использовать другой макет (возможно, созданный вами).

Немного математики делает трюк легче. Код, написанный Крисом Вагнером, ужасен, потому что он вызывает атрибуты макета каждого из предыдущих элементов. Таким образом, чем больше вы прокручиваете, тем медленнее...

Просто используйте по модулю вот так (я использую в качестве максимального значения также значение mininInteritemSpacing):

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewLayoutAttributes* currentItemAttributes = [super layoutAttributesForItemAtIndexPath:indexPath];
    NSInteger numberOfItemsPerLine = floor([self collectionViewContentSize].width / [self itemSize].width);

    if (indexPath.item % numberOfItemsPerLine != 0)
    {
        NSInteger cellIndexInLine = (indexPath.item % numberOfItemsPerLine);

        CGRect itemFrame = [currentItemAttributes frame];
        itemFrame.origin.x = ([self itemSize].width * cellIndexInLine) + ([self minimumInteritemSpacing] * cellIndexInLine);
        currentItemAttributes.frame = itemFrame;
    }

    return currentItemAttributes;
}

Простой способ выравнивания влево - изменить layoutAttributesForElementsInRect: в вашем подклассе UICollectionViewFlowLayout:

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
    NSArray *allLayoutAttributes = [super layoutAttributesForElementsInRect:rect];
    CGRect prevFrame = CGRectMake(-FLT_MAX, -FLT_MAX, 0, 0);
    for (UICollectionViewLayoutAttributes *layoutAttributes in allLayoutAttributes)
    {
        //fix blur
        CGRect theFrame = CGRectIntegral(layoutAttributes.frame);

        //left justify
        if(prevFrame.origin.x > -FLT_MAX &&
           prevFrame.origin.y >= theFrame.origin.y &&
           prevFrame.origin.y <= theFrame.origin.y) //workaround for float == warning
        {
            theFrame.origin.x = prevFrame.origin.x +
                                prevFrame.size.width + 
                                EXACT_SPACE_BETWEEN_ITEMS;
        }
        prevFrame = theFrame;

        layoutAttributes.frame = theFrame;
    }
    return allLayoutAttributes;
}

Решение Clean Swift из истории эволюции:

  1. был матовый ответ
  2. Крис Вагнер исправил одинокие вещи
  3. появилось мокагио, раздел Inset и минимальный InteritemSpacing улучшение
  4. вышла фанпая версия Swift
  5. Теперь вот упрощенная и чистая моя версия:
open class UICollectionViewLeftAlignedLayout: UICollectionViewFlowLayout {
    open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        return super.layoutAttributesForElements(in: rect)?.map { $0.representedElementKind == nil ? layoutAttributesForItem(at: $0.indexPath)! : $0 }
    }

    open override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        guard let currentItemAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes,
            collectionView != nil else {
            // should never happen
            return nil
        }

        // if the current frame, once stretched to the full row intersects the previous frame then they are on the same row
        if indexPath.item != 0,
            let previousFrame = layoutAttributesForItem(at: IndexPath(item: indexPath.item - 1, section: indexPath.section))?.frame,
            currentItemAttributes.frame.intersects(CGRect(x: -.infinity, y: previousFrame.origin.y, width: .infinity, height: previousFrame.size.height)) {
            // the next item on a line
            currentItemAttributes.frame.origin.x = previousFrame.origin.x + previousFrame.size.width + evaluatedMinimumInteritemSpacingForSection(at: indexPath.section)
        } else {
            // the first item on a line
            currentItemAttributes.frame.origin.x = evaluatedSectionInsetForSection(at: indexPath.section).left
        }
        return currentItemAttributes
    }

    func evaluatedMinimumInteritemSpacingForSection(at section: NSInteger) -> CGFloat {
        return (collectionView?.delegate as? UICollectionViewDelegateFlowLayout)?.collectionView?(collectionView!, layout: self, minimumInteritemSpacingForSectionAt: section) ?? minimumInteritemSpacing
    }

    func evaluatedSectionInsetForSection(at index: NSInteger) -> UIEdgeInsets {
        return (collectionView?.delegate as? UICollectionViewDelegateFlowLayout)?.collectionView?(collectionView!, layout: self, insetForSectionAt: index) ?? sectionInset
    }
}

Использование: расстояние между предметами определяется делегатом collectionView (_:layout:minimumInteritemSpacingForSectionAt:),

Я поместил его на github, https://github.com/Coeur/UICollectionViewLeftAlignedLayout, где я фактически добавил функцию поддержки обоих направлений прокрутки (горизонтального и вертикального).

Быстрая версия решения Криса.

class PazLeftAlignedCollectionViewFlowLayout : UICollectionViewFlowLayout {
    var maxCellSpacing = 14.0
    override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? {
        if var attributesToReturn = super.layoutAttributesForElementsInRect(rect) as? Array<UICollectionViewLayoutAttributes> {
            for attributes in attributesToReturn {
                if attributes.representedElementKind == nil {
                    let indexPath = attributes.indexPath
                    attributes.frame = self.layoutAttributesForItemAtIndexPath(indexPath).frame;
                }
            }
            return attributesToReturn;
        }
        return super.layoutAttributesForElementsInRect(rect)
    }

    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! {
        let currentItemAttributes = super.layoutAttributesForItemAtIndexPath(indexPath)

        if let collectionViewFlowLayout = self.collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
            let sectionInset = collectionViewFlowLayout.sectionInset
            if (indexPath.item == 0) { // first item of section
                var frame = currentItemAttributes.frame;
                frame.origin.x = sectionInset.left; // first item of the section should always be left aligned
                currentItemAttributes.frame = frame;

                return currentItemAttributes;
            }

            let previousIndexPath = NSIndexPath(forItem:indexPath.item-1, inSection:indexPath.section)
            let previousFrame = self.layoutAttributesForItemAtIndexPath(previousIndexPath).frame;
            let previousFrameRightPoint = Double(previousFrame.origin.x) + Double(previousFrame.size.width) + self.maxCellSpacing

            let currentFrame = currentItemAttributes.frame
            var width : CGFloat = 0.0
            if let collectionViewWidth = self.collectionView?.frame.size.width {
                width = collectionViewWidth
            }
            let strecthedCurrentFrame = CGRectMake(0,
                currentFrame.origin.y,
                width,
                currentFrame.size.height);

            if (!CGRectIntersectsRect(previousFrame, strecthedCurrentFrame)) { // if current item is the first item on the line
                // the approach here is to take the current frame, left align it to the edge of the view
                // then stretch it the width of the collection view, if it intersects with the previous frame then that means it
                // is on the same line, otherwise it is on it's own new line
                var frame = currentItemAttributes.frame;
                frame.origin.x = sectionInset.left; // first item on the line should always be left aligned
                currentItemAttributes.frame = frame;
                return currentItemAttributes;
            }

            var frame = currentItemAttributes.frame;
            frame.origin.x = CGFloat(previousFrameRightPoint)
            currentItemAttributes.frame = frame;
        }
        return currentItemAttributes;
    }
}

Чтобы использовать это, сделайте следующее:

    override func viewDidLoad() {
    super.viewDidLoad()
    self.collectionView.collectionViewLayout = self.layout
}
var layout : PazLeftAlignedCollectionViewFlowLayout {
    var layout = PazLeftAlignedCollectionViewFlowLayout()
    layout.itemSize = CGSizeMake(220.0, 230.0)
    layout.minimumLineSpacing = 12.0
    return layout
}

"Проблема" с UICollectionViewFlowLayout является то, что он применяет выравнивание по выравниванию к ячейкам: первая ячейка в строке выравнивается по левому краю, последняя ячейка в строке выравнивается по правому краю, а все остальные ячейки между ними равномерно распределяются с равным интервалом, который больше, чем minimumInteritemSpacing,

Уже есть много хороших ответов на этот пост, которые решают эту проблему путем создания подклассов UICollectionViewFlowLayout, В результате вы получите макет, который выравнивает ячейки слева. Другое правильное решение для распределения ячеек с постоянным интервалом - выравнивание ячеек вправо.

AlignedCollectionViewFlowLayout

Я создал UICollectionViewFlowLayout подкласс, который следует аналогичной идее, предложенной Мэттом и Крисом Вагнером, который может либо выровнять ячейки

⬅︎ слева:

Выровненный по левому краю макет

или ➡︎ правильно:

Выровненный по правому краю макет

Вы можете просто скачать его отсюда, добавить файл макета в свой проект и установить AlignedCollectionViewFlowLayout как класс макета представления вашей коллекции:
https://github.com/mischa-hildebrand/AlignedCollectionViewFlowLayout

Как это работает (для выровненных по левому краю ячеек):

 +---------+----------------------------------------------------------------+---------+
 |         |                                                                |         |
 |         |     +------------+                                             |         |
 |         |     |            |                                             |         |
 | section |- - -|- - - - - - |- - - - +---------------------+ - - - - - - -| section |
 |  inset  |     |intersection|        |                     |   line rect  |  inset  |
 |         |- - -|- - - - - - |- - - - +---------------------+ - - - - - - -|         |
 | (left)  |     |            |             current item                    | (right) |
 |         |     +------------+                                             |         |
 |         |     previous item                                              |         |
 +---------+----------------------------------------------------------------+---------+

Концепция здесь состоит в том, чтобы проверить, занимают ли текущая ячейка с индексом i и предыдущая ячейка с индексом i-1 одну и ту же строку.

  • Если они этого не делают, ячейка с индексом i является самой левой ячейкой в ​​строке.
    → Переместите ячейку к левому краю представления коллекции (не изменяя ее вертикальное положение).
  • Если это так, ячейка с индексом i не является самой левой ячейкой в ​​строке.
    → Получить кадр предыдущей ячейки (с индексом i-1) и переместить текущую ячейку рядом с ней.

Для выровненных по правому краю ячеек...

... вы делаете то же самое наоборот, т.е. вместо этого вы проверяете следующую ячейку с индексом i+1.

Сделать это можно двумя способами.

Во-первых, внесите некоторые изменения в layoutAttributesForItem,

получить макет текущего атрибута через предыдущий layoutAttributesForItem(at: IndexPath(item: indexPath.item - 1, section: indexPath.section))?.frame.

layoutAttributesForItem(at:): этот метод предоставляет информацию о макете по запросу в представление коллекции. Вам необходимо переопределить его и вернуть атрибуты макета для элемента по запрошенному indexPath.

Во-вторых, новые атрибуты через UICollectionViewLayoutAttributes(forCellWith: indexPath)размещайте их там, где хотите.

И математика немного больше, потому что она выполняет тяжелую работу по макету.

layoutAttributesForElements(in:): в этом методе вам нужно вернуть атрибуты макета для всех элементов внутри данного прямоугольника. Вы возвращаете атрибуты в представление коллекции как массив UICollectionViewLayoutAttributes.


Вы можете проверить Мое репо

  • вы можете выровнять элементы по левому краю

  • вы можете выровнять элементы правильно

  • вы можете расположить элементы по правому краю, а элементы - наоборот

Более простая и быстрая версия для заинтересованных людей, основанная на ответе Криса Вагнера:

class AlignLeftFlowLayout: UICollectionViewFlowLayout {

    var maximumCellSpacing = CGFloat(9.0)

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

        for attributes in attributesToReturn ?? [] {
            if attributes.representedElementKind == nil {
                attributes.frame = self.layoutAttributesForItemAtIndexPath(attributes.indexPath).frame
            }
        }

        return attributesToReturn
    }

    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! {
        let curAttributes = super.layoutAttributesForItemAtIndexPath(indexPath)
        let sectionInset = (self.collectionView?.collectionViewLayout as UICollectionViewFlowLayout).sectionInset

        if indexPath.item == 0 {
            let f = curAttributes.frame
            curAttributes.frame = CGRectMake(sectionInset.left, f.origin.y, f.size.width, f.size.height)
            return curAttributes
        }

        let prevIndexPath = NSIndexPath(forItem: indexPath.item-1, inSection: indexPath.section)
        let prevFrame = self.layoutAttributesForItemAtIndexPath(prevIndexPath).frame
        let prevFrameRightPoint = prevFrame.origin.x + prevFrame.size.width + maximumCellSpacing

        let curFrame = curAttributes.frame
        let stretchedCurFrame = CGRectMake(0, curFrame.origin.y, self.collectionView!.frame.size.width, curFrame.size.height)

        if CGRectIntersectsRect(prevFrame, stretchedCurFrame) {
            curAttributes.frame = CGRectMake(prevFrameRightPoint, curFrame.origin.y, curFrame.size.width, curFrame.size.height)
        } else {
            curAttributes.frame = CGRectMake(sectionInset.left, curFrame.origin.y, curFrame.size.width, curFrame.size.height)
        }

        return curAttributes
    }
}

Вот это для NSCollectionViewFlowLayout

class LeftAlignedCollectionViewFlowLayout: NSCollectionViewFlowLayout {

    var maximumCellSpacing = CGFloat(2.0)

    override func layoutAttributesForElementsInRect(rect: NSRect) -> [NSCollectionViewLayoutAttributes] {

        let attributesToReturn = super.layoutAttributesForElementsInRect(rect)

        for attributes in attributesToReturn ?? [] {
            if attributes.representedElementKind == nil {
                attributes.frame = self.layoutAttributesForItemAtIndexPath(attributes.indexPath!)!.frame
            }
        }
        return attributesToReturn
    }

    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> NSCollectionViewLayoutAttributes? {

        let curAttributes = super.layoutAttributesForItemAtIndexPath(indexPath)
        let sectionInset = (self.collectionView?.collectionViewLayout as! NSCollectionViewFlowLayout).sectionInset

        if indexPath.item == 0 {
            let f = curAttributes!.frame
            curAttributes!.frame = CGRectMake(sectionInset.left, f.origin.y, f.size.width, f.size.height)
            return curAttributes
        }

        let prevIndexPath = NSIndexPath(forItem: indexPath.item-1, inSection: indexPath.section)
        let prevFrame = self.layoutAttributesForItemAtIndexPath(prevIndexPath)!.frame
        let prevFrameRightPoint = prevFrame.origin.x + prevFrame.size.width + maximumCellSpacing

        let curFrame = curAttributes!.frame
        let stretchedCurFrame = CGRectMake(0, curFrame.origin.y, self.collectionView!.frame.size.width, curFrame.size.height)

        if CGRectIntersectsRect(prevFrame, stretchedCurFrame) {
            curAttributes!.frame = CGRectMake(prevFrameRightPoint, curFrame.origin.y, curFrame.size.width, curFrame.size.height)
        } else {
            curAttributes!.frame = CGRectMake(sectionInset.left, curFrame.origin.y, curFrame.size.width, curFrame.size.height)
        }

        return curAttributes
    }
}

Быстрая версия базы на mokagio: https://github.com/fanpyi/UICollectionViewLeftAlignedLayout-Swift

class UICollectionViewLeftAlignedLayout: UICollectionViewFlowLayout {
    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let attributesToReturn = super.layoutAttributesForElementsInRect(rect)
        if let attributesToReturn = attributesToReturn {
            for attributes in attributesToReturn {
                if attributes.representedElementKind == nil {
                    let indexpath = attributes.indexPath
                    if let attr = layoutAttributesForItemAtIndexPath(indexpath) {
                        attributes.frame = attr.frame
                    }

                }
            }
        }
        return attributesToReturn
    }

    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? {
        if  let currentItemAttributes = super.layoutAttributesForItemAtIndexPath(indexPath){
            let sectionInset = self.evaluatedSectionInsetForItemAtIndex(indexPath.section)
            let  isFirstItemInSection = indexPath.item == 0;
            let  layoutWidth = CGRectGetWidth(self.collectionView!.frame) - sectionInset.left - sectionInset.right;

            if (isFirstItemInSection) {
                currentItemAttributes.leftAlignFrameWithSectionInset(sectionInset)
                return currentItemAttributes
            }

            let  previousIndexPath = NSIndexPath(forItem: indexPath.item - 1, inSection: indexPath.section)

            let previousFrame = layoutAttributesForItemAtIndexPath(previousIndexPath)?.frame ?? CGRectZero
            let  previousFrameRightPoint = previousFrame.origin.x + previousFrame.width
            let currentFrame = currentItemAttributes.frame;
            let  strecthedCurrentFrame = CGRectMake(sectionInset.left,
                currentFrame.origin.y,
                layoutWidth,
                currentFrame.size.height)
            // if the current frame, once left aligned to the left and stretched to the full collection view
            // widht intersects the previous frame then they are on the same line
            let  isFirstItemInRow = !CGRectIntersectsRect(previousFrame, strecthedCurrentFrame)

            if (isFirstItemInRow) {
                // make sure the first item on a line is left aligned
                currentItemAttributes.leftAlignFrameWithSectionInset(sectionInset)
                return currentItemAttributes
            }

            var frame = currentItemAttributes.frame;
            frame.origin.x = previousFrameRightPoint + evaluatedMinimumInteritemSpacingForSectionAtIndex(indexPath.section)
            currentItemAttributes.frame = frame;
            return currentItemAttributes;

        }
        return nil
    }
    func evaluatedMinimumInteritemSpacingForSectionAtIndex(sectionIndex:Int) -> CGFloat {
        if let delegate = self.collectionView?.delegate as? UICollectionViewDelegateFlowLayout {
            if delegate.respondsToSelector("collectionView:layout:minimumInteritemSpacingForSectionAtIndex:") {
                return delegate.collectionView!(self.collectionView!, layout: self, minimumInteritemSpacingForSectionAtIndex: sectionIndex)

            }
        }
        return self.minimumInteritemSpacing

    }
    func evaluatedSectionInsetForItemAtIndex(index: Int) ->UIEdgeInsets {
        if let delegate = self.collectionView?.delegate as? UICollectionViewDelegateFlowLayout {
            if  delegate.respondsToSelector("collectionView:layout:insetForSectionAtIndex:") {
                return delegate.collectionView!(self.collectionView!, layout: self, insetForSectionAtIndex: index)
            }
        }
        return self.sectionInset
    }
}
Другие вопросы по тегам