如何设置没有换行符的水平UICollectionViewFlowLayout

时间:2014-05-28 15:01:10

标签: ios uicollectionviewlayout

目前我有一个水平滚动的标准UICollectionViewFlowLayout,但如果高度允许,它会将项目相互堆叠。
相反,我希望有一个水平滚动的集合视图,不会断行,即不会将项目相互堆叠 - 只需一个线性流。
这个问题甚至比this question更简单,因为不需要垂直滚动。因此那里的答案不适用。

我想我可以继承UICollectionViewFlowLayout,但我不确定哪些方法必须被覆盖 我检查了在显示项目之前调用了当前-layoutAttributesForElementsInRect:(但不是-layoutAttributesForItemAtIndexPath:NSArray返回的-layoutAttributesForElementsInRect:包含每个项目的框架(其中一些是相互堆叠的)。
我可以在-collectionView:layout:sizeForItemAtIndexPath:中抑制这种堆叠,如果我在这个方法中增加所有项目的高度大于最大高度的一半,但是项目本身是垂直缩放的,这是我不想要的。

所以我的问题是:什么以及如何覆盖UICollectionViewFlowLayoutUICollectionViewLayout的方法来获得这种线性流?

1 个答案:

答案 0 :(得分:0)

我自己解决了这个问题,但也许这有助于其他人 我部分使用了Bryan Hansen的UICollectionView custom layout tutorial

我将UICollectionViewFlowLayout子类化,添加了属性,并且只实现了3种方法(下面的伪代码):

@interface LinearCollectionViewFlowLayout : UICollectionViewFlowLayout
@end  

@interface LinearCollectionViewFlowLayout ()
@property (nonatomic, strong) NSArray *layoutInfo;    // layout infos for the collection view elements
@property                     CFFloat *maxItemHeight; // max height of items in the collection view
@end

@implementation LinearCollectionViewFlowLayout

- (void)prepareLayout
{
    // Get from the collection views datasource an array of all items in the collection view
    ......

    // Loop through all items and store max height in the property.
    ......

    CGFloat xOffsetOfNextItem = 0;
    NSMutableArray *tmpLayoutInfo = [NSMutableArray array];
    // Loop through all items to compute x and y origin of every item in the collection view
    for (int index = 0; index < nrCollectionViewItems; index++) {
        // Get the next item via its index and store it in a variable nextItem
        ......
        CGSize  nextItemSize   = nextItem.size;       // Get the size of the next item
        CGFloat nextItemHeight = nextItemSize.height; // Get the height of the next item

        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0]; // Assuming that there is only 1 section in the collection view
        UICollectionViewLayoutAttributes *itemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
        CGFloat yOffset = self.maxItemHeight/2.0 - nextImageHeight/2.0 + 5; // center the item vertically (add spacer)
        CGRect itemFrame = CGRectMake(xOffsetOfNextItem, yOffset, nextItemSize.width, nextItemHeight);
        itemAttributes.frame = itemFrame; // store the frame of the item
        tmpLayoutInfo[index] = itemAttributes;

        xOffsetOfNextIcon += nextItemSize.width + 5; // Compute x of next item (add a spacer)
    }
    self.collectionView.contentWidth = xOffsetOfNextItem; // Store the width of the collection view

    self.layoutInfo = [NSArray arrayWithArray:tmpLayoutInfo]; // Store all layout infos
}

//-----------------------------------------------------------------------------------------------------------------

- (CGSize)collectionViewContentSize
{
    CGSize size = [super collectionViewContentSize]; // Get the collection view size as computed by UICollectionViewFlowLayout
    size.width = self.collectionView.contentWidth;   // Replace the width by the value computed in prepareLayout
    return size;
}

//-----------------------------------------------------------------------------------------------------------------

-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
{
    // Set up an array of layout attributes only for the items in rect
    NSMutableArray *attributesForElementsInRect = [NSMutableArray array];
    for (UICollectionViewLayoutAttributes *nextAttributes in self.layoutInfo) {
        CGRect nextFrame = nextAttributes.frame;
        if (CGRectIntersectsRect(rect, nextFrame)) {
            [attributesForElementsInRect addObject:nextAttributes];
        }
    }

    return [NSArray arrayWithArray:attributesForElementsInRect];
}

@end