2017-02-21 78 views
1

我需要創建具有不同大小(1x1,2x2,2x1,3x2.5)的單元格的UICollectionView。我已經編碼添加單元,具體取決於他們使用的尺寸是collectionView:layout:sizeForItemAtIndexPath:UICollectionView中的單元格順序

這裏預期結果(小區1和3具有以對電池2的左側):
enter image description here

但是,目前的結果是:
enter image description here

我(難看)當前的代碼(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之上,但在c的左側埃爾2?

我不想做一個不會改變的靜態佈局,因爲將來每個單元的大小可能不同。例如,單元格2可能是2x1大小...

哪種方法可以做到這一點?我期待指定到UICollectionViewLayout一個流(如「從頂部」),但它不會像這樣工作...

+2

我認爲你必須繼承'UICollectionViewLayout',在那裏你會給每個單元格的框架。 – Larme

回答

8

子類化UICollectionViewLayout的示例示例。 所有的值都是硬編碼的,只是爲了明確它背後的邏輯。當然,這可以進行優化。

@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]; 

渲染: enter image description here

+0

Wooh!它完美的作品。非常感謝你。我只會嘗試重寫幾個硬編碼的部分。 – Jonathan

+0

@Larme,真的很有幫助。再次感謝,+ 1投票 –

1

這是同樣的邏輯Larme建議。但使用較少的硬編碼,並且可以在不添加新的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 

然後,我創建2個屬性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和而已。你可以找到更多的信息和迅速版本here