【问题标题】:Resize UICollectionView cells after image inside has been downloaded下载内部图像后调整 UICollectionView 单元格的大小
【发布时间】:2014-04-16 22:57:58
【问题描述】:

我正在构建一个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 大小的正确方法是什么?

【问题讨论】:

    标签: ios uicollectionview uicollectionviewcell


    【解决方案1】:

    当图像返回时,您应该能够使动画块中的集合视图布局无效。如果不止一张图片一次完成,事情可能会变得有点复杂,但这应该可以:

    [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 */;
    }
    

    【讨论】:

    • 谢谢!第一次加载 UICollectionView 时我得到了一个完美的结果,但是当它第二次加载时(即移动到另一个视图并返回),我得到了奇怪的单元格框架大小(小于预期,内容重叠)。如果我滚动一下,一切都会再次正确显示。下载图像后是否必须更改单元格框架大小(以及位置)?
    • 已解决。实际上,细胞框架没有任何作用。我只需要在 animateWithDuration 块之前设置 cell.imageView 框架。 [cell.imageView setFrame:CGRectMake(2,2,image.size.width,image.size.height])]; [UIView animateWithDuration:0.3f animations:^{ [self.collectionView.collectionViewLayout invalidateLayout]; }];
    • 我是否应该通过回调以这种方式调用它,因为如果我这样做我有一个问题,因为它需要一个返回表达式,因为我在每个单元格上都调用了它? stackoverflow.com/questions/23316634/…我就是这么写的,实际上是在尝试调整大小,但它不保持纵横比而是剪掉了一部分图像?
    • 你在 sizeForItemAtIndexPath 方法中返回了什么?
    【解决方案2】:

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

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

    如果单元格的大小是动态的,则从索引路径中获取单元格并根据图像的大小返回其大小。我通常为单元格创建一个返回动态大小的方法,就像上面的示例一样。您可以使用 UIImage 的 size 属性来帮助返回基于图像的大小。

    【讨论】:

    • 下载完所有图像后,我应该何时重新加载收藏视图?或者最好用 reloadItemsAtIndexPaths 重新加载每个单元格?
    • 以这种方式下载所有图像后,您必须重新加载集合视图。
    • +1 因为即使您的回答没有解决我的问题,我还是使用了 [cell size] 方法的想法。但是@Ash 解决方案正是我想要的。
    • 您不应该多次调用 dequeueReusableCellWithReuseIdentifier: 而不将单元格返回到集合中,例如在 cellForItemAtIndexPath:.该集合将有数百个已出列的单元格,这些单元格将永远不会被重新使用。
    • @Matt,感谢您指出这一点!我更新了答案以使用cellForItemAtIndexPath:
    【解决方案3】:

    您可以尝试reloadItemsAtIndexPaths: 获取已完成加载的单元格。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-29
      • 1970-01-01
      • 2013-02-24
      • 2021-09-28
      • 2020-06-26
      • 1970-01-01
      • 2012-11-24
      相关资源
      最近更新 更多