我有一个水平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。然后,图像被拉伸以填充图像视图。
当我向右滚动然后向后滚动时,这些单元将从集合视图中删除并重新装入,现在已经正确地布置了:
在滚动时,单元格会调整其宽度,有时会调整到正确的宽度,有时会调整到错误的宽度。
我在这里做什么错了?
答案 0 :(得分:3)
由于图像是异步传入的,因此可能需要一些时间来加载。只有将它们加载后,您才能真正知道图像的大小或比例。这意味着对于每个加载的图像,您都需要“重新加载”布局。通过简短的搜索,this看起来很有希望。
至少通过这种方式,您可能会获得一些动画,否则,当图像开始加载时,您的单元格只会继续跳跃。
无论如何,我建议您避免这种情况。如果我可以假设的话;您从服务器获取了一些数据,您使用这些数据从服务器使用传递的URL下载图像并将其显示在集合视图中。最好的方法(如果可能)是请求扩展API,以便您也接收图像的尺寸。所以代替
{
id: 1,
image: "https://..."
}
您可以拥有
{
id: 1,
image: {
url: "https://...",
width: 100,
height: 100
}
}
现在,您可以在下载图像之前使用这些值生成宽高比的宽度/高度。
此外,我并没有看到任何使整体看起来不错(没有跳来跳去)的好的解决方案。