8

J'ai créé un UICollectionViewLayout personnalisé et je l'ai placé dans mon contrôleur de vue de collection dans le storyboard. Je n'ai pas eu beaucoup de problèmes sur l'affichage des éléments/cellules. Mon problème est que viewForSupplementaryElementOfKind n'est pas appelé. Je ne peux pas sembler indiquer exactement pourquoi. J'ai essayé de revenir à la disposition par défaut et il l'appelle alors mais j'ai besoin de mon UICollectionViewLayout personnalisé. J'ai quitté NSLogs pour vérifier et viewForSupplementaryElementOfKind n'est pas appelé.viewForSupplementaryElementOfKind ne fait pas l'objet d'un appel personnalisé UICollectionViewLayout

Voici mon 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); 
} 

Voici mon 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; 

}

Comme vous pouvez le voir dans MyFlowLayout, il y a des choses que j'ai essayé mais il n'appelait toujours pas viewForSupplementaryElementOfKind. J'ai essayé d'implémenter layoutAttributesForItemAtIndexPath depuis que j'ai layoutAttributesForSupplementaryViewOfKind. J'ai aussi essayé d'utiliser des nombres fixes comme les 75 et 320 que vous voyez juste pour vérifier si l'en-tête serait généré. Le délégué que vous voyez, c'est juste pour obtenir une hauteur de vue.

Depuis que j'ai donné l'espace suffisant d'en-tête à voir et NSLogs laissé partout et encore (UICollectionReusableView *) CollectionView: (UICollectionView *) CollectionView viewForSupplementaryElementOfKind: (NSString *) type atIndexPath: (NSIndexPath *) indexPath n'est pas être appelé.

Voici quelques-uns que j'ai regardé et essayé: stackoverflow mais comme vous pouvez le voir dans le code commenté que j'ai inclus. Cela n'a toujours pas fonctionné.

Merci pour l'aide.

+0

Hey, n'a pas trouvé une réponse? parce que j'ai le même problème que vous – Ali

+0

ouais encore n'ai pas trouvé un. Je lis une bibliothèque appelée CHTCollectionViewWaterfallLayout et comment ils l'ont fait jusqu'ici je n'ai pas trouvé la réponse. – Revin

Répondre

5

J'ai aussi eu un problème était d'ajouter simplement avec cela et ma solution attributs de section 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

Ajouter la taille par défaut de la section d'en-tête:

collectionViewLayout.headerReferenceSize = CGSize(width, height) 

Les valeurs de taille par défaut sont (0, 0). C'est pourquoi l'en-tête ne s'affiche pas.

OU

Il y a aussi une autre façon pour elle, mettre en œuvre la méthode déléguée pour UICollectionView:

collectionView(_:layout:referenceSizeForFooterInSection:) 
+0

Ceci devrait être la réponse acceptée. – shoujs