具有异步图像加载功能的自定义UICollectionView单元格

时间:2019-03-20 11:28:20

标签: ios swift asynchronous uicollectionview

我有一个水平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受到单元格宽度的影响。

以下是运行我的应用程序时的结果:

wrong cell widths

如您所见,尽管已加载图像并更新了布局,但单元的宽度为400。然后,图像被拉伸以填充图像视图。
当我向右滚动然后向后滚动时,这些单元将从集合视图中删除并重新装入,现在已经正确地布置了:

right cell widths

在滚动时,单元格会调整其宽度,有时会调整到正确的宽度,有时会调整到错误的宽度。

我在这里做什么错了?

1 个答案:

答案 0 :(得分:3)

由于图像是异步传入的,因此可能需要一些时间来加载。只有将它们加载后,您才能真正知道图像的大小或比例。这意味着对于每个加载的图像,您都需要“重新加载”布局。通过简短的搜索,this看起来很有希望。

至少通过这种方式,您可能会获得一些动画,否则,当图像开始加载时,您的单元格只会继续跳跃。

无论如何,我建议您避免这种情况。如果我可以假设的话;您从服务器获取了一些数据,您使用这些数据从服务器使用传递的URL下载图像并将其显示在集合视图中。最好的方法(如果可能)是请求扩展API,以便您也接收图像的尺寸。所以代替

{
    id: 1,
    image: "https://..."
}

您可以拥有

{
    id: 1,
    image: {
        url: "https://...",
        width: 100,
        height: 100
    } 
}

现在,您可以在下载图像之前使用这些值生成宽高比的宽度/高度。

此外,我并没有看到任何使整体看起来不错(没有跳来跳去)的好的解决方案。