2017-02-21 8 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]; 

レンダリング:Larmeが提案されているよう enter image description here

+0

うわー!それは完全に動作します。どうもありがとうございました。ハードコーディングされた部分を少し書き直そうとします。 – Jonathan

+0

@Larme、本当に助けになります。ありがとうございます、+ 1投票 –

1

ここでは、同じロジックです。しかしハードコードは少なく、新しいアイテムを追加することなく、あなたが望むアイテムの数を設定することができます。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を見つけることができます。

関連する問題