具有异步图像加载的自调整 UICollectionView 单元格
Posted
技术标签:
【中文标题】具有异步图像加载的自调整 UICollectionView 单元格【英文标题】:Self-sizing UICollectionView cells with async image loading 【发布时间】:2019-03-20 11:28:20 【问题描述】:我有一个水平的UICollectionView
,我在其中显示异步加载的图像。单元格的宽度应该适合图像。
在我的视图控制器的viewDidLoad
中,我设置了估计的单元格大小:
(collectionView.collectionViewLayout as? UICollectionViewFlowLayout)?.estimatedItemSize = CGSize(width: 400, height: 400)
在cellForItem
,我使用Kingfisher启动下载任务:
cell.imageView.kf.setImage(with: url) (_, _, _, _) in
cell.layoutSubviews()
在我的单元格中,layoutSubviews
方法中有以下代码:
// 326 is the image view's height
// .aspectRatio is a custom extension that returns: size.width / size.height
imageViewWidthConstraint.constant = 326 * image.aspectRatio
layoutIfNeeded()
在情节提要中,我已正确设置布局约束,以便单元格宽度尊重imageViewWidthConstraint
。
以下是运行我的应用时的结果:
如您所见,单元格的宽度为 400,尽管已加载图像并更新了布局。因此,图像会被拉伸以填充图像视图。 当我向右滚动然后返回时,单元格将从集合视图中删除并重新加载,现在布局正确:
在滚动时,单元格会调整它们的宽度,有时会调整到正确的宽度,有时会调整到错误的宽度。
我在这里做错了什么?
【问题讨论】:
嗨,我刚刚用 tableView 实现了同样的东西。这是Link。我必须保持宽度不变并根据图像尺寸动态调整高度。看看代码以获得一个想法。基本上,您应该在SizeForItemAt IndexPath
返回大小,并且您的图像应该固定到集合视图。
@AwaisFayyaz 您如何为收藏视图执行此操作?
【参考方案1】:
由于您的图片是异步传入的,因此加载可能需要一些时间。只有加载它们后,您才能真正知道图像的大小或比例。这意味着对于加载的每个图像,您都需要“重新加载”您的布局。从简短的搜索来看,this 看起来很有希望。
至少这样你可能会得到一些动画,否则你的单元格会在图像开始加载时不断跳跃。
无论如何,我建议您避免这种情况。如果我可以假设;您正在从服务器获取一些数据,您使用提供的 URL 从中下载图像并将它们显示在集合视图上。最好的方法(如果可能的话)是请求扩展 API,以便您也接收图像的尺寸。所以不是
id: 1,
image: "https://..."
你可以有
id: 1,
image:
url: "https://...",
width: 100,
height: 100
您现在可以在下载图像之前使用这些值生成宽高比宽度/高度。
除此之外,我真的没有看到任何好的解决方案让整个事情看起来不错(不跳来跳去)。
【讨论】:
图像确实需要一秒钟才能加载,但布局没有更新...感谢在 API 响应中传递宽度和高度参数的建议,我可能会这样做它应该会产生最佳的视觉效果。 不过,我不会接受你的回答,因为从技术上讲,它不能回答我的问题? 也许有一天有人会提出解决方案。改为thanks。 @LinusGeffarth "但是布局没有更新";该部分应由我提供的链接修复。但问题是您需要将该代码放入您正在使用的工具的某个回调中,以便在图像视图上设置新图像... 确实,我之前有过reloadItems(at:)
,在每张图片下载完成后我都会调用它。问题是当滚动 b/c 新单元格加载时它会跳来跳去......
@LinusGeffarth 它也可以启用分页。想象一下,您将创建一个对单个页面的请求,并获得 200 个项目,它们都具有一个图像。此时,您还不会调用完成块,而是为每个图像创建 200 个并行 HEAD 请求。一旦你得到 200 个大小,你就可以将大小注入到你的有效负载中,然后调用完成。所以基本上你会保留完全相同的系统,但等待那些额外的数据。以上是关于具有异步图像加载的自调整 UICollectionView 单元格的主要内容,如果未能解决你的问题,请参考以下文章
在 UITableViewCells 中显示之前调整图像大小和裁剪图像
如何调整 UIImageView 的大小并强制重新布局父 UITableViewCell