6

Ich versuche, ein benutzerdefiniertes Flow-Layout für eine UICollectionView zu definieren, indem ich UICollectionViewFlowLayout unterklassifiziere. Das Layout ich wie folgt aussieht wollen:UICollectionViewFlowLayout leerer Bereich mit variabler Zellenbreite und -höhe

layout

Wie Sie sehen können, habe ich die Sammlung Ansicht in 2 gleiche Reihen entlang der horizontalen Mitte Kluft gespalten. Die obere Reihe ist in drei Drittel unterteilt, und die unteren Reihen teilen sich in zwei Spalten.

Alles scheint und gut aussehen zu arbeiten, bis Sie nach rechts scrollen (die Sammlung Ansicht Scrollen UICollectionViewScrollDirectionHorizontal ist) und es einen großen Raum zu sehen, nachdem die 5-Zellen gemacht zu werden fertig:

layout

Ich habe keine Ahnung, warum das passiert, aber es scheint, dass der leere Raum etwa die gleiche Breite wie eine Zelle aus der oberen Reihe aussieht; ein Drittel der Breite der Sammlungsansicht.

Hier ist, wie ich Setup die UICollectionView und UICollectionViewFlowLayout Unterklasse

- (void)loadView { 
    [super loadView]; 
    [self setupCollectionView]; 
} 

- (void)setupCollectionView { 
    CustomFlowLayout *flowLayout = [[CustomFlowLayout alloc] init]; 
    flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal; 
    flowLayout.minimumInteritemSpacing = 0.0; 
    flowLayout.minimumLineSpacing = 0.0f; 

    CGRect frame = CGRectMake(0, 0, 748, 1024); 
    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:flowLayout]; 

    [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:CollectionViewCellID]; 

    collectionView.delegate = self; 
    collectionView.dataSource = self; 

    collectionView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 

    collectionView.backgroundColor = [UIColor whiteColor]; 

    collectionView.pagingEnabled = YES; 


    self.collectionView = collectionView; 

    [self.view addSubview:self.collectionView]; 
} 

#pragma mark - UICollectionViewDataSource 
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { 
    return 1; 
} 

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 

    return 5; 
} 

Die Größe der Elemente in der Sammlung Ansicht von der Layout-Konfiguration für einen bestimmten Abschnitt definiert ist, so dass ich implementieren collectionView:layout:sizeForItemAtIndexPath: wie so:

- (CGSize)collectionView:(UICollectionView *)collectionView 
        layout:(UICollectionViewLayout*)collectionViewLayout 
    sizeForItemAtIndexPath:(NSIndexPath *)indexPath { 

    return [collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath].size; 

} 

Meine benutzerdefinierte Unterklasse von UICollectionViewLayout wird wie folgt implementiert:

@implementation CustomFlowLayout 

- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { 
    NSArray* attributesToReturn = [super layoutAttributesForElementsInRect:rect]; 
    for (UICollectionViewLayoutAttributes* attributes in attributesToReturn) { 
     if (nil == attributes.representedElementKind) { 
      NSIndexPath* indexPath = attributes.indexPath; 
      attributes.frame = [self layoutAttributesForItemAtIndexPath:indexPath].frame; 
     } 
    } 
    return attributesToReturn; 
} 

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { 
    UICollectionViewLayoutAttributes* currentItemAttributes = [super layoutAttributesForItemAtIndexPath:indexPath]; 

    if (!currentItemAttributes) { 
     currentItemAttributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 
    } 

    float height = self.collectionView.frame.size.height; 
    float width = self.collectionView.frame.size.width; 

    CGRect frame = CGRectZero;  
    switch (indexPath.row) { 
     case 0: 
      frame.size = CGSizeMake(width/3, height/2); 
      frame.origin = CGPointMake(0, 0); 
      break; 
     case 1: 
      frame.size = CGSizeMake(width/3, height/2); 
      frame.origin = CGPointMake(width/3, 0); 
      break; 
     case 2: 
      frame.size = CGSizeMake(width/3, height/2); 
      frame.origin = CGPointMake(2*width/3, 0); 
      break; 
     case 3: 
      frame.size = CGSizeMake(width/2, height/2); 
      frame.origin = CGPointMake(0, height/2); 
      break; 
     case 4: 
      frame.size = CGSizeMake(width/2, height/2); 
      frame.origin = CGPointMake(width/2, height/2); 
      break; 
     default: 
      break; 
    } 

    currentItemAttributes.frame = frame; 
    currentItemAttributes.size = frame.size; 
    return currentItemAttributes; 
} 

Wer hat irgendwelche Ideen, warum ich den großen leeren Raum habe, nachdem alle Zellen gerendert wurden? Oder hat jemand einen besseren Ansatz, um das Layout, nach dem ich gesucht habe, zu rendern? Der gesamte Code ist als Beispiel für das XCode-Projekt here verfügbar. Antworten, Tipps, Gedanken, Pull-Anfragen werden sehr geschätzt.

Antwort

4

Das Problem schien zu sein, dass, wenn es zwei Reihen von Zellen gab, die unterschiedliche Breiten hatten, die contentSize des collectionview so berechnet wurde, dass ein Bereich des weißen Raumes rechts blieb. Ein einfacher war notwendig, um das Problem zu beheben:

- (CGSize)collectionViewContentSize { 
    return CGSizeMake(1024, 748); 
} 

die Github Repo mit den Änderungen aktualisiert here. Hoffe das hilft jemandem in der Zukunft.