2
votes

I've started developing an app with a pinterest-like layout with UICollectionView with different cell heights and contents. I've defined a template cell (label + UIImageView) which is used throught the cellForItemAtIndexPath callback.

In that specific function (cellForItemAtIndexPath) I'm modifying the content (UIImage) and the size of the UIImageView element to respect the ratio of the new image and use the full width of the current Cell.

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

FRGWaterfallCollectionViewCell *waterfallCell = [collectionView dequeueReusableCellWithReuseIdentifier:WaterfallCellIdentifier forIndexPath:indexPath];

[waterfallCell.layer setMasksToBounds:YES];
[waterfallCell.layer setCornerRadius:10.0];
[waterfallCell.layer setBorderWidth:1.0];
[waterfallCell.layer setBorderColor:[[UIColor darkGrayColor] CGColor]];
[waterfallCell.layer setNeedsDisplayOnBoundsChange:YES];

// some variables init
.....

// Get the new image
UIImage *image = [UIImage imageNamed: [NSString stringWithFormat: @"photo_%d.jpg", no_image]];

// Compute the image ratio
CGFloat largeur_img = image.size.width;
CGFloat hauteur_img = image.size.height;
CGFloat viewRatio = hauteur_img / largeur_img;

// Modify the UIImageView frame
CGRect cadre = waterfallCell.img_doc.frame;
<b>waterfallCell.img_doc.frame = CGRectMake(cadre.origin.x,cadre.origin.y,cadre.size.width, ceil(cadre.size.width * viewRatio));</b>

// We set the image of the UIImageView
<b>[waterfallCell.img_doc setImage:image];</b>

// Force to redraw the cell
<b>[waterfallCell setNeedsDisplay];</b>

return waterfallCell;

}

However, this Cell is not refresh or redrawn...except when I scroll down the UICollectionView and go back to the top, then my UIImageView for each cell are in a correct shape. I've searched on the web, seen many posts regarding setNeedsDisplay but here it seems that the Cell use the CALayer so it is not concerned.. I've understand that the refresh in on the main thread but I do not know how to fire this refresh in order to get at the first display, the correct cells with correct sub-UIImageView with their right dimensions.

Thanks for your help,

Regards

Nicolas

2
Have you tried resetting the parameters in prepareForReuse method of your custom UICollectionViewCell?ManicMonkOnMac
Have you found any solution. I am facing the exact same problem.Aleem Ahmad

2 Answers

0
votes

The problem is right here :

FRGWaterfallCollectionViewCell *waterfallCell = [collectionView dequeueReusableCellWithReuseIdentifier:WaterfallCellIdentifier forIndexPath:indexPath];

On the first time you open the controller, there are no cells to be dequeued, so waterfallCell will be nil. ( if you want you can add a log to verify this). Only when you will scroll, the cells will be dequeued, that's why only when you scroll you can see the diferences.

What I do, when I use customised collection view cells :

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellIdentifier = @"catalogOneRowCell";
    LACatalogOneRowCell *catalogCell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];

    if (catalogCell == nil) {
        catalogCell = [LACatalogOneRowCell getLACatalogOneRowCell];
    }

Here is the LaCatalogOneRowCell.m

 + (LACatalogOneRowCell *)getLACatalogOneRowCell {
      NSArray *xib = [[NSBundle mainBundle] loadNibNamed:@"LACatalogOneRowCell" owner:nil options:nil];
      for (NSObject *obj in xib) {
          if ([obj isKindOfClass:[LACatalogOneRowCell class]]) {
              return (LACatalogOneRowCell *)obj;
          }
      }
     return nil;

}

And very important, in your viewDidLoad, register the nib of your cell:

UINib *nib = [UINib nibWithNibName:@"LACatalogOneRowCell" bundle:nil];
[catalogCollectionView registerNib:nib forCellWithReuseIdentifier:@"catalogOneRowCell"];

Also, i do not recommed alocing in cellforRow:

UIImage *image = [UIImage imageNamed:... 

is the same as UIImage *image = [[[UIImage alloc] initWithImage:.... ] autorelease];

It is bad for performance to alloc objects in cellForRow, especially objects like UIImage

0
votes

In my opinion, you should dequeue based on ratio. This will save you from a lot of pain trying to put everything together. Whatever happens your items will have a limit set of ratios anyway. Plus I'm not sure you can change the frame of a cell that's already been used without kicking off a large reload of the view which would be quite costly in terms of CPU.