8

Ho creato un UICollectionViewLayout personalizzato e l'ho inserito nel mio View Controller di raccolta nello storyboard. Non ho avuto molti problemi nel mostrare gli oggetti/le celle. Il mio problema è che viewForSupplementaryElementOfKind non viene chiamato. Non riesco a individuare il motivo per cui è così. Ho provato a tornare al layout predefinito e lo chiama, ma ho bisogno del mio UICollectionViewLayout personalizzato. Ho lasciato NSLogs per controllare e viewForSupplementaryElementOfKind non viene chiamato.viewForSupplementaryElementOfKind non richiamato personalizzato UICollectionViewLayout

Ecco il mio MyCollectionViewController.m

- (void)viewDidLoad { 
[super viewDidLoad]; 
// Do any additional setup after loading the view. 
viewArray = [NSMutableArray array]; 

//setup the delegate for vertical flow layout 
[(VerticalFlowLayout*)self.collectionViewLayout setDelegate:self]; 

//register the headers 
[self.collectionView registerNib:[ButtonHeaderCollectionReusableView nib] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:[ButtonHeaderCollectionReusableView reusableID]]; 

//set the insets 
[self.collectionView setContentInset:UIEdgeInsetsMake(23, 5, 10, 5)]; } 

#pragma mark - CollectionView DataSource 

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 
return [self.cardsArray count]; 
} 

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { 
NSLog(@"Number of Sections"); 

return 1; 
} 

-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 

NSLog(@"Making Card"); 

CardCell *card = [collectionView dequeueReusableCellWithReuseIdentifier:@"CardCell" forIndexPath:indexPath]; 

// UILabel *cardLabel = [card viewWithTag:101]; 
// [cardLabel setText:[textArray objectAtIndex:[indexPath row]]]; 

return card; 
} 

-(UICollectionReusableView*)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { 

NSLog(@"Making Header"); 

UICollectionReusableView *reusableView = nil; /*[[UICollectionReusableView alloc] initWithFrame:CGRectMake(0, 0, 100, 75)];*/ 
// [reusableView setBackgroundColor:[UIColor blackColor]]; 

if (kind == UICollectionElementKindSectionHeader) { 
    ButtonHeaderCollectionReusableView *headerview = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:[ButtonHeaderCollectionReusableView reusableID] forIndexPath:indexPath]; 

    return headerview; 
} 

// if (kind == UICollectionElementKindSectionFooter) { 
//  UICollectionReusableView *footerview = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"FooterView" forIndexPath:indexPath]; 
// } 

return reusableView; 
} 

-(CGSize)collectionView:collectionView layout:(nonnull UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section { 
return CGSizeMake(180.0f, 72.0f); 
} 

Ora qui è la mia MyFlowLayout.m

-(id)initWithCoder:(NSCoder *)aDecoder { 
NSLog(@"Vertical Flow Layout init with coder"); 
if(self = [super initWithCoder:aDecoder]) { 
    contentHeight = 0; 
    cachedAttributes = [NSMutableArray array]; 
} 

return self; 
} 

-(void)prepareLayout { 
NSLog(@"Preparing Layout"); 
// [super prepareLayout]; 

contentWidth = CGRectGetWidth(self.collectionView.bounds) - (self.collectionView.contentInset.left + self.collectionView.contentInset.right); 

if([cachedAttributes count] == 0) { 
    //compute for column width 
    CGFloat columnWidth = contentWidth/NUMBER_OF_COLUMNS; 
    NSMutableArray *xOffsets = [NSMutableArray array]; 
    for(int i = 0; i < NUMBER_OF_COLUMNS; i++) { 
     [xOffsets addObject:[NSNumber numberWithFloat:(i * columnWidth)]]; 
    } 

    //compute for height 
    NSMutableArray *yOffsets = [NSMutableArray array]; 
    for(int i = 0; i < NUMBER_OF_COLUMNS; i++) { 
     [yOffsets addObject:[NSNumber numberWithFloat:75]]; 
    } 

    int column = 0; 
    //loop through all the sections and items in the collectionview 
    for(int i = 0; i < self.collectionView.numberOfSections; i++) { 
     for(int j = 0; j < [self.collectionView numberOfItemsInSection:i]; j++) { 
      NSIndexPath *indexPath = [NSIndexPath indexPathForItem:j inSection:i]; 

      //time to do some frame calculation 
      ///let's start with the width 
      CGFloat width = columnWidth - CELL_PADDING * 2; 
      ///then the height 
      CGFloat viewHeight = [self.delegate getViewHeightWithCollectionView:self.collectionView indexPath:indexPath withWidth:width]; 
      CGFloat height = CELL_PADDING + viewHeight + /*textHeight +*/ CELL_PADDING; 

      CGFloat xOffset = [[xOffsets objectAtIndex:column] floatValue]; 
      CGFloat yOffset = [[yOffsets objectAtIndex:column] floatValue]; 

      CGRect frame = CGRectMake(xOffset, yOffset, columnWidth, height); 
      CGRect insetFrame = CGRectInset(frame, CELL_PADDING, CELL_PADDING); 

      //now that computation is done we shall make the attributes 
      UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 
      [attributes setFrame:insetFrame]; 
      [cachedAttributes addObject:attributes]; 

      //time to increment the height and the column 
      contentHeight = MAX(contentHeight, CGRectGetMaxY(frame)); 
      NSNumber *yOffSetColumn = [yOffsets objectAtIndex:column]; 
      yOffSetColumn = [NSNumber numberWithFloat:([yOffSetColumn floatValue] + height)]; 
      [yOffsets replaceObjectAtIndex:column withObject:yOffSetColumn]; 

      NSLog(@"Content Height: %f yOffSetColumn: %@ == %@", contentHeight, yOffSetColumn, [yOffsets objectAtIndex:column]); 

      column = column >= (NUMBER_OF_COLUMNS - 1) ? 0 : ++column; 
     } 
    } 
} 
} 

-(CGSize)collectionViewContentSize { 
// NSLog(@"Collection View Content Size"); 
return CGSizeMake(contentWidth, contentHeight + 75); 
} 

//called after preparelayout to determine which items are visible in the given rect 
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect { 
NSMutableArray 

<UICollectionViewLayoutAttributes *> *layoutAttributes = [NSMutableArray array]; 

NSInteger sectionsCount = [self.collectionView.dataSource numberOfSectionsInCollectionView:self.collectionView]; 

NSLog(@"Sections count: %ld", (long)sectionsCount); 

for(int i = 0; i < sectionsCount; i++) { 
    //for header 
    UICollectionViewLayoutAttributes *headerAttributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:i]]; 
//  if(CGRectIntersectsRect(headerAttributes.frame, rect)) { 
//   NSLog(@"Adding Section Attribute"); 
     [layoutAttributes addObject:headerAttributes]; 
//  } 

    for (UICollectionViewLayoutAttributes *attributes in cachedAttributes) { 
     if(CGRectIntersectsRect(attributes.frame, rect)) { 
      [layoutAttributes addObject:attributes]; 
     } 
    } 

//  NSInteger itemsCount = [self.collectionView numberOfItemsInSection:i]; 
//  for(int j = 0; j < itemsCount; j++) { 
//   UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:j inSection:i]]; 
//   if(CGRectIntersectsRect(attributes.frame, rect)) { 
//    [layoutAttributes addObject:attributes]; 
//   } 
//  } 
    } 


return layoutAttributes; 
} 

//-(UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { 
// NSLog(@"Layout Attributes For Item: %ld %ld", [indexPath row], [indexPath section]); 
//  
// UICollectionViewLayoutAttributes *attributes = [cachedAttributes objectAtIndex:[indexPath row]]; 
// return attributes; 
//} 

-(UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath { 

NSLog(@"Layout Attributes For Header: %@ %ld %ld", elementKind, [indexPath row], [indexPath section]); 

UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; 
[attributes setFrame:CGRectMake(0, 0, contentWidth /*320*/, 75.0f)]; 

return attributes; 

}

Come potete vedere nel MyFlowLayout, ci sono cose che ho provato ma ancora non ha chiamato viewForSupplementaryElementOfKind. Ho provato a implementare layoutAttributesForItemAtIndexPath poiché ho layoutAttributesForSupplementaryViewOfKind. Ho provato anche a usare numeri fissi come il 75 e il 320 che vedi per verificare se l'intestazione sarebbe stata generata. Il delegato che vedi, è solo per ottenere un'altezza di una vista.

Da quando ho dato lo spazio sufficiente intestazione di essere visto e lasciato NSLogs tutto e tuttavia (UICollectionReusableView *) CollectionView: (UICollectionView *) CollectionView viewForSupplementaryElementOfKind: (NSString *) tipo atIndexPath: (NSIndexPath *) indexPath non è essere chiamato.

Ecco alcuni che ho guardato e provato: stackoverflow ma come puoi vedere dal codice commentato che ho incluso. Ancora non ha funzionato.

Grazie per l'aiuto.

+0

Ehi, non ha trovato una risposta? perché ho lo stesso problema di te – Ali

+0

sì non l'ho ancora trovato. Sto leggendo una biblioteca chiamata CHTCollectionViewWaterfallLayout e come l'hanno fatto finora non ho trovato la risposta. – Revin

risposta

5

Ho anche avuto un problema con questo e la mia soluzione era quella di aggiungere semplicemente gli attributi per sezione prepareLayout

UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]]; 
attributes.frame = CGRectMake(0, 0, self.collectionView.frame.size.width, 100); 
[cachedAttributes addObject:attributes]; 
4

Aggiungere la dimensione predefinita di sezione di intestazione:

valori delle dimensioni
collectionViewLayout.headerReferenceSize = CGSize(width, height) 

Il default sono (0, 0). Ecco perché l'intestazione non viene visualizzata.

O

C'è anche un altro modo per esso, implementare il metodo delegato per UICollectionView:

collectionView(_:layout:referenceSizeForFooterInSection:) 
+0

Questa dovrebbe essere la risposta accettata. – shoujs