web-dev-qa-db-fra.com

UICollectionView avec une hauteur dynamique ne disposant pas du même espace entre les cellules

J'ai un problème similaire comme ça

Je génère une hauteur de vue au moment de l'exécution. Voici mon code

@interface CollectionViewController ()
{
    NSMutableArray *arrMain;
}
@property(nonatomic,strong) NSMutableArray *arrMain;
@end

@implementation CollectionViewController
@synthesize arrMain,


- (void)viewDidLoad
{
    [super viewDidLoad];

    [cView registerNib:[UINib nibWithNibName:@"CViewCell" bundle:nil] forCellWithReuseIdentifier:kCellID];

    CViewFlowLayout *fl = [[CViewFlowLayout alloc] init];
    self.cView.collectionViewLayout = fl;

    NSString *strJson = MY FUNCTION WHICH RETURNS JSON STRING;
    SBJSON *parser = [[SBJSON alloc] init];

    self.arrMain = [[NSMutableArray alloc] init];
    self.arrMain = [parser objectWithString:strJson error:nil];
    for (int i=0; i<[self.arrMain count]; i++) {
        NSDictionary *dic = [self.arrMain objectAtIndex:i];
        [self setTags:[[UIView alloc] init] selDictionary:dic];  // This function generates height and save it to the dictionary
    }
    [cView reloadData];
}

- (NSInteger)collectionView:(UICollectionView *)view numberOfItemsInSection:(NSInteger)section;
{
    return [self.arrMain count];
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{

    NSDictionary *dic = [self.arrMain objectAtIndex:indexPath.row];
    return CGSizeMake(236,40+[[dic valueForKey:@"TAGS_HEIGHT"] intValue]);
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath;
{

    CViewCell *cell =(CViewCell *) [cv dequeueReusableCellWithReuseIdentifier:kCellID forIndexPath:indexPath];
    NSDictionary *dic = [self.arrMain objectAtIndex:indexPath.row];
    if ([cell viewWithTag:11]){
        [[cell viewWithTag:11] release];
        [[cell viewWithTag:11] removeFromSuperview];
    }
    UIView *viewTags = [[UIView alloc] init];
    [viewTags setTag:11];
    [viewTags setBackgroundColor:[UIColor lightGrayColor]];
    [self setTags:viewTags selDictionary:dic];
    [viewTags setFrame:CGRectMake(5, 10, CONTENT_WIDTH, [[dic valueForKey:@"TAGS_HEIGHT"] floatValue])];
    [cell.contentView addSubview:viewTags];

    return cell;
}

J'avais essayé la solution ci-dessus, mais cela ne fonctionnait pas pour moi. Voici une image de ma sortie.

J'ai besoin que l'espacement soit le même. Quelqu'un at-il une solution à ce problème?

Est-ce que ce bogue de UICOllectionView? Parce que j'ai trouvé ce problème dans cet article aussi.

10
Viral Narshana

J'ai la solution générale pour ce genre de problème:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [cView registerNib:[UINib nibWithNibName:@"CViewCell" bundle:nil] forCellWithReuseIdentifier:kCellID];

    CViewFlowLayout *fl = [[CViewFlowLayout alloc] init];
    fl.minimumInteritemSpacing = 10;
    fl.scrollDirection = UICollectionViewScrollDirectionVertical;
    self.cView.collectionViewLayout = fl;

    NSString *strJson = MY FUNCTION WHICH RETURNS JSON STRING;
    SBJSON *parser = [[SBJSON alloc] init];

    self.arrMain = [[NSMutableArray alloc] init];
    self.arrMain = [parser objectWithString:strJson error:nil];
    for (int i=0; i<[self.arrMain count]; i++) {
    NSDictionary *dic = [self.arrMain objectAtIndex:i];
    [self setTags:[[UIView alloc] init] selDictionary:dic];  // This function generates height and save it to the dictionary
}
    [cView reloadData];

}

Ensuite, mettez à jour le code dans CViewFlowLayout.m, qui est une sous-classe de UICollectionViewFlowLayout.

Voici le code:

#define numColumns 3
@implementation CViewFlowLayout
@synthesize numOfColumnsToDisplay;
- (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 (indexPath.item < numColumns){
        CGRect f = currentItemAttributes.frame;
        f.Origin.y = 0;
        currentItemAttributes.frame = f;
        return currentItemAttributes;
    }
    NSIndexPath* ipPrev = [NSIndexPath indexPathForItem:indexPath.item-numColumns inSection:indexPath.section];
    CGRect fPrev = [self layoutAttributesForItemAtIndexPath:ipPrev].frame;
    CGFloat YPointNew = fPrev.Origin.y + fPrev.size.height + 10;
    CGRect f = currentItemAttributes.frame;
    f.Origin.y = YPointNew;
    currentItemAttributes.frame = f;
    return currentItemAttributes;
}

Cette solution fonctionnera uniquement avec le défilement vertical. Si vous souhaitez afficher plus ou moins de colonnes, modifiez simplement la variable numColumns.

7
Viral Narshana

Essaye ça:

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

    return CGSizeMake(250, 150);
}
3
svmrajesh

La classe dont vous avez hérité de UICollectionViewFlowLayout doit contenir les méthodes suivantes: 

- (CGSize)collectionViewContentSize
{
    return CGSizeMake(200, 200) // as per your cell size
}

- (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];
    }
    return currentItemAttributes;
}

Et dans votre CollectionViewController ajouter 

#pragma mark - Collection View Datasource

- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout  *)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    // Adjust cell size for orientation
    if (UIDeviceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))
    {
        return CGSizeMake(150, 230);
    }
    return CGSizeMake(150, 230);
}
1
Swati

Vous pouvez définir la taille avec une propriété:

flowLayout.headerReferenceSize = CGSizeMake(0, 100);//constant height for all the items header

Si dynamique:

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

    return CGSizeZero;
}
1
Kumar KL

enter image description here

1
Muralikrishna

Utiliser la méthode suivante 

//Rapide

func collectionView(_ collectionView: UICollectionView,
    layout collectionViewLayout: UICollectionViewLayout,
    sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize{
 return CGSizeMake(250, 150);
}

//Objectif c

-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(250, 150);
}
1
Sankalp S Raul