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

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

enter image description here

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

Ответ 1

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


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

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

С кодом @matt, который я видел.

enter image description here

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

enter image description here

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

Ответ 2

Чтобы получить максимальное межсимвольное расстояние, подкласс 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 уже сделал для нас. Он уже решил, сколько предметов идет в каждой строке; мы просто читаем эти строки и собираем предметы вместе, если вы понимаете, что я имею в виду.

Ответ 3

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

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

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

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

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

Ответ 4

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

Просто используйте modulo, как это (я также использую значение minimumInteritemSpacing как максимальное значение):

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

Ответ 5

Простым способом для выравнивания по левому краю является изменение 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;
}

Ответ 6

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

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

Ответ 7

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

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

AlignedCollectionViewFlowLayout

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

⬅︎ слева:

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

или ➡︎ справа:

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

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

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

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

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

  • Если они не являются ячейкой с индексом i, это самая большая ячейка в строке.

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

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

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

Ответ 8

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

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, где я фактически добавил функцию поддержки обоих направлений прокрутки (по горизонтали и по вертикали).

Ответ 9

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

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

Ответ 10

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

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

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

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

Во-вторых, UICollectionViewLayoutAttributes(forCellWith: indexPath) новые атрибуты через UICollectionViewLayoutAttributes(forCellWith: indexPath), UICollectionViewLayoutAttributes(forCellWith: indexPath) их в любом месте.

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

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


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

  • Вы можете поставить элементы влево

9236j.png

  • Вы можете расположить предметы по правому краю

I6LFb.png

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

rYuSh.png

Ответ 11

Здесь для 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
    }
}

Ответ 12

версия быстрой версии на 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
    }
}