在UICollectionView中的单元格顺序

我需要创build一个UICollectionView与不同大小的单元格( UICollectionView )。 我已经编码添加单元格,取决于他们使用的是什么尺寸的collectionView:layout:sizeForItemAtIndexPath:

这是预期的结果(单元格1和单元格3必须位于单元格2的左侧):
在这里输入图像说明

但是目前的结果是:
在这里输入图像说明

我的(丑)目前的代码是(self.cellSize =屏幕宽度/ 3):

 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { CGFloat size = self.cellSize; if (indexPath.item == 0) { return CGSizeMake(self.cellSize * 3.f, self.cellSize * 2.5f); } if (indexPath.item == 1) { return CGSizeMake(self.cellSize, self.cellSize); } if (indexPath.item == 2) { return CGSizeMake(self.cellSize * 2.f, self.cellSize * 2.f); } if (indexPath.item == 3) { return CGSizeMake(self.cellSize, self.cellSize); } if (indexPath.item == 4) { return CGSizeMake(self.cellSize * 2.f, self.cellSize); } if (indexPath.item == 5) { return CGSizeMake(self.cellSize, self.cellSize); } if (indexPath.item == 6) { return CGSizeMake(self.cellSize, self.cellSize); } if (indexPath.item == 7) { return CGSizeMake(self.cellSize * 2.f, self.cellSize); } if (indexPath.item == 8) { return CGSizeMake(self.cellSize * 3.f, self.cellSize * 2.5f); } return CGSizeMake(size, size); } 

有没有办法指定单元格3必须高于单元格1,但在单元格2的左侧?

我不想做一个不会改变的静态布局,因为将来每个单元的大小可能不同。 例如,单元格2可能是2×1大小…

哪个是最好的方法呢? 我期待指定到UICollectionViewLayoutstream(如“从顶部”),但它不能这样工作…

通过inheritanceUICollectionViewLayout的示例。 所有的值都是硬编码的,只是为了明确它背后的逻辑。 当然,这可以优化。

 @interface CustomCollectionViewLayout () @property (nonatomic, strong) NSMutableDictionary *cellLayouts; @property (nonatomic, assign) CGSize unitSize; @end @implementation CustomCollectionViewLayout -(id)initWithSize:(CGSize)size { self = [super init]; if (self) { _unitSize = CGSizeMake(size.width/3,150); _cellLayouts = [[NSMutableDictionary alloc] init]; } return self; } -(void)prepareLayout { for (NSInteger i = 0; i < [[self collectionView] numberOfItemsInSection:0]; i ++) { NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0]; UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; CGRect frame; switch ([indexPath item]) { case 0: frame = CGRectMake(0, 0, _unitSize.width*3, _unitSize.height*2.5); break; case 1: frame = CGRectMake(0, _unitSize.height*2.5, _unitSize.width, _unitSize.height); break; case 2: frame = CGRectMake(_unitSize.width, _unitSize.height*2.5, _unitSize.width*2, _unitSize.height*2); break; case 3: frame = CGRectMake(0, _unitSize.height*2.5+_unitSize.height, _unitSize.width, _unitSize.height); break; case 4: frame = CGRectMake(0, _unitSize.height*2.5+_unitSize.height+_unitSize.height, _unitSize.width*2, _unitSize.height); break; case 5: frame = CGRectMake(_unitSize.width*2, _unitSize.height*2.5+_unitSize.height+_unitSize.height, _unitSize.width, _unitSize.height); break; case 6: frame = CGRectMake(0, _unitSize.height*2.5+_unitSize.height+_unitSize.height+_unitSize.height, _unitSize.width, _unitSize.height); break; case 7: frame = CGRectMake(_unitSize.width, _unitSize.height*2.5+_unitSize.height+_unitSize.height+_unitSize.height, _unitSize.width*2, _unitSize.height); break; case 8: frame = CGRectMake(0, _unitSize.height*2.5+_unitSize.height+_unitSize.height+_unitSize.height+_unitSize.height, _unitSize.width*3, _unitSize.height*2.5); break; default: frame = CGRectZero; break; } [attributes setFrame:frame]; [[self cellLayouts] setObject:attributes forKey:indexPath]; } } -(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { NSMutableArray *retAttributes = [[NSMutableArray alloc] init]; for (NSIndexPath *anIndexPath in [self cellLayouts]) { UICollectionViewLayoutAttributes *attributes = [self cellLayouts][anIndexPath]; if (CGRectIntersectsRect(rect, [attributes frame])) { [retAttributes addObject:attributes]; } } return retAttributes; } -(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { return [self cellLayouts][indexPath]; } -(CGSize)collectionViewContentSize { return CGSizeMake(_unitSize.width*3, _unitSize.height*9); } @end 

那么,你只需要打电话:

 CustomCollectionViewLayout *layout = [[CustomCollectionViewLayout alloc] initWithSize:self.myCollectionView.bounds.frame.size]; [self.myCollectionView setCollectionViewLayout:layout]; 

渲染: 在这里输入图像说明

这和Larmebuild议的逻辑是一样的。 但使用较less的硬编码,并且可以在不添加新的case:设置所需项目的数量。

我称之为“模式”一组5个项目。 所以首先我定义常量值:

 #define MAX_COLUMN 3 // Max columns in the pattern #define MAX_LINE_PER_PATTERN 3 // Max lines in the pattern #define PATTERN_ITEM_COUNT 5 // Max items in the pattern 

然后我创build了一个自定义布局,其中包含两个属性NSMutableArray *layoutAttributesCGFloat contentHeight ,其中我需要重写这些方法:

 - (void)prepareLayout{ [super prepareLayout]; if (!self.layoutAttributes){ self.layoutAttributes = [[NSMutableArray alloc] init]; CGFloat cellWidth = self.collectionView.frame.size.width / MAX_COLUMN; CGFloat cellHeight = cellWidth; self.contentHeight = 0.f; for (int item = 0 ; item < [self.collectionView numberOfItemsInSection:0] ; item ++){ CGFloat width, height = 0.f; CGFloat xPos, yPos = 0.f; NSInteger patternCount = (NSInteger)((CGFloat)item / (CGFloat)PATTERN_ITEM_COUNT); NSInteger currentIndex = item % PATTERN_ITEM_COUNT; switch (currentIndex) { case 0: { xPos = 0.f; yPos = 0.f + MAX_LINE_PER_PATTERN * cellHeight * patternCount; width = cellWidth; height = cellHeight; self.contentHeight += cellHeight; break; } case 1: { xPos = cellWidth; yPos = 0.f + MAX_LINE_PER_PATTERN * cellHeight * patternCount; width = cellWidth * 2.f; height = cellHeight * 2.f; self.contentHeight += cellHeight; break; } case 2: { xPos = 0.f; yPos = cellHeight + MAX_LINE_PER_PATTERN * cellHeight * patternCount; width = cellWidth; height = cellHeight; break; } case 3: { xPos = 0.f; yPos = 2.f * cellHeight + MAX_LINE_PER_PATTERN * cellHeight * patternCount; width = cellWidth * 2.f; height = cellHeight; self.contentHeight += cellHeight; break; } case 4: { xPos = 2.f * cellWidth; yPos = 2.f * cellHeight + MAX_LINE_PER_PATTERN * cellHeight * patternCount; width = cellWidth; height = cellHeight; break; } default: NSLog(@"error with index"); break; } UICollectionViewLayoutAttributes *attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:[NSIndexPath indexPathForRow:item inSection:0]]; attr.frame = CGRectMake(xPos, yPos, width, height); [self.layoutAttributes addObject:attr]; } } } - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{ NSMutableArray *currentAttributes = [NSMutableArray new]; for (UICollectionViewLayoutAttributes *attr in self.layoutAttributes) { if (CGRectIntersectsRect(attr.frame, rect)) { [currentAttributes addObject:attr]; } } return currentAttributes; } - (CGSize)collectionViewContentSize{ return CGSizeMake(self.collectionView.frame.size.width, self.contentHeight); } 

然后将这个自定义布局分配给self.collectionView.collectionViewLayout ,就是这样。 你可以在这里find更多的信息和快捷版本。