图片下载完成后调整UICollectionView单元格大小

17

我正在创建一个UICollectionView,我的自定义单元格将包含两个标签和一个图像。

每个图像都是异步下载的,因此在下载完成之前我不知道它的大小。 一旦下载完成,我想适应每个单元格以重新布局其内容和框架,以适合刚下载的图像的高度。

作为UICollectionViewLayout,我正在使用CHTCollectionViewWaterfallLayout

为了异步下载图像,我正在使用SDWebImage,如下所示:

    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
                   placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                          completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) 
                                {... some completion code here ...}];

问题:

在每个图像下载完成后,正确的方法是调整每个UICollectionViewCell的大小吗?

3个回答

28

当图像重新出现时,您只需在动画块中使您的集合视图布局无效即可。如果有多个图像同时完成,则可能会变得有些复杂,但这应该可以解决:

[cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
               placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                      completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType)^{
                          [UIView animateWithDuration:0.3f animations:^{
                              [self.collectionView.collectionViewLayout invalidateLayout];
                          }];
                      }];

然后只需在适当的委托方法中返回不同的大小即可。

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    return /* a different size if the image is done downloading yet */;
}

1
谢谢!第一次加载UICollectionView时,我得到了完美的结果,但是当它第二次加载时(即移动到另一个视图并返回),我会得到奇怪的单元格框架大小(比预期小,内容重叠)。 如果我滚动一下,一切都会再次正确显示。 在图像下载后,我是否需要更改单元格框架大小(以及在哪里更改)? - Fmessina
2
已解决。实际上,与单元格框架无关。我只需要在 animateWithDuration 块之前设置 cell.imageView 框架即可。[cell.imageView setFrame:CGRectMake(2,2,image.size.width,image.size.height])]; [UIView animateWithDuration:0.3f animations:^{ [self.collectionView.collectionViewLayout invalidateLayout]; }]; - Fmessina
我是否应该使用回调来调用它,因为如果我这样做,由于它在每个单元格上被调用,所以它期望一个返回表达式,所以我遇到了问题?http://stackoverflow.com/questions/23316634/how-to-cache-image-and-scale-it-correctly 这就是我写的方式,实际上我正在尝试调整大小,但它不会保持纵横比,而是裁剪图像的一部分? - Lion789
你在 sizeForItemAtIndexPath 方法中返回了什么? - Waqar Khalid

1

要调整集合视图单元格的大小,您可以重新加载集合视图,并在以下方法中动态返回您的集合视图单元格的大小:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
    return [cell size];
}

在单元格大小动态的情况下,可以从索引路径获取单元格,并根据图像大小返回其大小。我通常会为单元格创建一个方法来返回动态大小,如上面的示例所示。您可以使用UIImage的size属性来帮助根据图像返回大小。


我应该在所有图片下载完成后重新加载集合视图吗?还是使用reloadItemsAtIndexPaths逐个重新加载单元格更好? - Fmessina
以这种方式做,您将不得不在下载所有图像后重新加载集合视图。 - Chris
+1 是因为即使你的答案没有解决我的问题,我还是使用了 [单元格大小] 方法的思路。不过 @Ash 的解决方案才是我想要的。 - Fmessina
在cellForItemAtIndexPath:中,您不应多次调用dequeueReusableCellWithReuseIdentifier:而不将单元格返回到集合中。集合中会有数百个已出列但从未返回以供重用的单元格。 - Matt
@Matt,感谢你指出这一点!我已经更新了答案,使用cellForItemAtIndexPath: - Chris

0
您可以尝试使用reloadItemsAtIndexPaths:方法来重新加载已完成加载的单元格。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接