目前我有一个水平滚动的标准UICollectionViewFlowLayout
,但如果高度允许,它会将项目相互堆叠。
相反,我希望有一个水平滚动的集合视图,不会断行,即不会将项目相互堆叠 - 只需一个线性流。
这个问题甚至比this question更简单,因为不需要垂直滚动。因此那里的答案不适用。
我想我可以继承UICollectionViewFlowLayout
,但我不确定哪些方法必须被覆盖
我检查了在显示项目之前调用了当前-layoutAttributesForElementsInRect:
(但不是-layoutAttributesForItemAtIndexPath:
)
NSArray
返回的-layoutAttributesForElementsInRect:
包含每个项目的框架(其中一些是相互堆叠的)。
我可以在-collectionView:layout:sizeForItemAtIndexPath:
中抑制这种堆叠,如果我在这个方法中增加所有项目的高度大于最大高度的一半,但是项目本身是垂直缩放的,这是我不想要的。
所以我的问题是:什么以及如何覆盖UICollectionViewFlowLayout
或UICollectionViewLayout
的方法来获得这种线性流?
答案 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