web-dev-qa-db-fra.com

UICollectionView: vue d'en-tête par programmation

C'est ainsi que je travaille sur l'en-tête.

  //    viewDidLoad

  [self.collectionView registerClass:[UICollectionViewCell class]forCellWithReuseIdentifier:@"Cell"];

[self.collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];

UICollectionViewFlowLayout *layout= [[UICollectionViewFlowLayout alloc]init];

self.collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, 390, 300) collectionViewLayout:layout];
layout.collectionView.backgroundColor = [UIColor colorWithRed:230.0/255.0 green:230.0/255.0 blue:230.0/255.0 alpha:1.0];
[self.collectionView registerClass:[UICollectionViewCell class]
        forCellWithReuseIdentifier:@"Cell"];
self.collectionView.delegate=self;
self.collectionView.dataSource=self;
layout.minimumInteritemSpacing = 15;

[layout setScrollDirection:UICollectionViewScrollDirectionVertical];

self.collectionView.collectionViewLayout = layout;
self.collectionView.showsHorizontalScrollIndicator = NO;
self.collectionView.showsVerticalScrollIndicator = NO;
[self.collectionView setBounces:YES];
self.collectionView.allowsMultipleSelection = YES;
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"HorizontalPickerCell"];
[self.view addSubview:self.collectionView];

   - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
  {
  if (section == 0) {
    return CGSizeMake(0, kHeaderHeight);
  }
  return CGSizeMake(0, kHeaderHeight + kInterSectionMargin);
  }

  - (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView
  {
NSLog(@"levels count:%d", [arrLevels count]);
return [arrLevels count];
  }

  - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
 {
 NSLog(@"vals count:%d", [arrSeats count]);
 for(int i=0; i<[arrLevels count]; i++)
 {
    if(section == i)
    {
        int c;
        NSString *cnt = [NSString stringWithFormat:@"%@",[arrTot objectAtIndex:i]];
        c = [cnt intValue];
        return c;
    }
 }
 return 1;
 }

 - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];

//cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"blue_s.png"]];

if (cell.selected) {
    [UIColor colorWithPatternImage:[UIImage imageNamed:@"blue_s.png"]]; // highlight selection
 }
else
 {
    cell.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"yellow_seat.png"]]; // Default color
 }

return cell;
 }

 - (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(10, 12, 10, 10);
 }

 - (CGSize)collectionView:(UICollectionView *)collectionView layout:  (UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGSize retval =  CGSizeMake(22, 20);
return retval;
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
UICollectionReusableView *reusableview = nil;

if (kind == UICollectionElementKindSectionHeader) {
    UICollectionReusableView *headerView = [self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:nil forIndexPath:indexPath];

        self.lblHeader = [[UILabel alloc]initWithFrame:CGRectMake(120, 10, 100, 30)];
        self.lblHeader.backgroundColor = [UIColor whiteColor];
        self.lblHeader.textColor = [UIColor redColor];
        self.lblHeader.text = @"Level 1";
        [self.collectionView addSubview:self.lblHeader];
}
return reusableview;
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
printf("Selected View index=%d",indexPath.row);

itemPaths  = [self.collectionView indexPathsForSelectedItems];

UICollectionViewCell* cell=[self.collectionView cellForItemAtIndexPath:indexPath];
cell.contentView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"blue_s.png"]];
 }

 - (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
 {
UICollectionViewCell* cell=[self.collectionView cellForItemAtIndexPath:indexPath];
cell.contentView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"yellow_seat.png"]];
 }

L'erreur que vous voyez est assez claire. Vous essayez de retirer une vue réutilisable, mais la vue de collection ne sait rien de l'identifiant de réutilisation que vous transmettez.

Vous devez appeler registerClass:forSupplementaryViewOfKind:withReuseIdentifier: avant dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath: est appelé. J'appelle généralement l'une des méthodes de registre dans viewDidLoad afin que toute la configuration soit terminée et je peux simplement appeler la méthode de dequeue. Si vous chargez vos vues d'en-tête et de pied de page personnalisées à partir de nib, vous pouvez utiliser le registerNib:forSupplementaryViewOfKind:withReuseIdentifier: méthode.

Éditer

Je vois que vous avez mis à jour le code. Vous devez déplacer ces lignes

UICollectionViewFlowLayout *layout= [[UICollectionViewFlowLayout alloc]init];

self.collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, 390, 300) collectionViewLayout:layout];

au-dessus des lignes où vous appelez les méthodes de classe de registre. Vous ne pouvez pas envoyer de messages à un objet avant de l'allouer et de l'initialiser.

14
CEarwood

Si vous n'affichez rien sur l'en-tête, comment pouvez-vous vous attendre à ce que la vue d'en-tête vous montre quelque chose sur la partie d'en-tête de UICollectionView.Essayez le code suivant.

- (void)viewDidLoad
{
    arry=[[NSArray alloc] initWithObjects:@"One",@"Two",@"Three",@"Four", nil];
    [_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cellIdentifier"];
    [self.collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView"];

    // Do any additional setup after loading the view, typically from a nib.
}


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

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 20;
}

// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cellIdentifier" forIndexPath:indexPath];

    if (cell==nil) {
        cell=[[UICollectionViewCell alloc] init];
    }

    UILabel *label = (UILabel*)[cell.contentView viewWithTag:21];

    if (label==nil) {
      label=[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 60, 60)];
      label.tag = 21;
      [cell.contentView addSubview:label];
    } 

    label.text = [arry objectAtIndex:indexPath.row];

    NSLog(@"cell is %@",NSStringFromCGRect(cell.frame));
    return cell;
}


- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return CGSizeMake(60, 60);
}

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
    UIEdgeInsets insets=UIEdgeInsetsMake(10, 10, 10, 10);
    return insets;
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {

        UICollectionReusableView *reusableview = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView" forIndexPath:indexPath];

        if (reusableview==nil) {
            reusableview=[[UICollectionReusableView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
        }

        UILabel *label=[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
        label.text=[NSString stringWithFormat:@"Recipe Group #%i", indexPath.section + 1];
        [reusableview addSubview:label];
        return reusableview;
    }
    return nil;
}
12
Warewolf

pourquoi ajoutez-vous lblHeader à self.collectionView ajouter à headerView.Et retourner headerView.Replace votre code avec lui

    if (kind == UICollectionElementKindSectionHeader) {
    UICollectionReusableView *headerView = [self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:nil forIndexPath:indexPath];

        self.lblHeader = [[UILabel alloc]initWithFrame:CGRectMake(120, 10, 100, 30)];
        self.lblHeader.backgroundColor = [UIColor whiteColor];
        self.lblHeader.textColor = [UIColor redColor];
        self.lblHeader.text = @"Level 1";

       // [self.collectionView addSubview:self.lblHeader];
          [headerView addSubview:self.lblHeader];

       return headerView;
}
4
Warewolf

En règle générale, vous placez cette ligne de registre dans le viewDidLoad ou une sorte d'initialisation afin qu'elle ne soit pas appelée maintes et maintes fois. Mais vous avez surtout une certaine confusion. Vous enregistrez une classe pour l'en-tête mais vous retirez une classe dans le pied de page. Vous devez enregistrer une classe pour les deux et retirer la bonne pour chacune.

Notez que votre registre utilise UICollectionElementKindSectionHeader:

[self.collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"header"];

Notez que votre file d'attente utilise UICollectionElementKindSectionFooter:

UICollectionReusableView *supplementaryView = [self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"header" forIndexPath:indexPath];

j'espère que cela pourra aider.

1
Aditya Nagrath

essaye ça :

    //ON top 
    static NSString *headerViewIdentifier = @"Test Header View";
    static NSString *footerViewIdentifier = @"Test Footer View";


    - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
    {
        NSString *identifier = nil;

        if ([kind isEqualToString:UICollectionElementKindSectionHeader]) {
            identifier = headerViewIdentifier;
        }
        else if ([kind isEqualToString:UICollectionElementKindSectionFooter]) {
            identifier = footerViewIdentifier;
        }

        // TODO Setup view

        UICollectionReusableView *supplementaryView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:identifier forIndexPath:indexPath];

        return supplementaryView;
    }
1
SAMIR RATHOD