Саморазмерные ячейки UICollectionView с асинхронной загрузкой изображений - PullRequest
1 голос
/ 20 марта 2019

У меня есть горизонтальная 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 Ответ

3 голосов
/ 20 марта 2019

Поскольку ваши изображения поступают асинхронно, загрузка может занять некоторое время. Только после их загрузки вы можете узнать размер или соотношение изображения. Это означает, что для каждого загружаемого изображения вам необходимо «перезагрузить» свой макет. Из короткого поиска это выглядит многообещающе.

По крайней мере, таким образом вы можете получить анимацию, иначе ваши ячейки будут продолжать прыгать, когда изображения начнут загружаться.

В любом случае я бы посоветовал вам этого избежать. Если я могу предположить; Вы получаете некоторые данные с сервера, с которого вы используете предоставленные URL-адреса для загрузки изображений и отображения их в представлении коллекции. Наилучший подход (если это возможно) - запросить расширение API для получения размеров изображений. Так что вместо

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

Вы могли бы иметь

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

Теперь вы можете использовать эти значения для генерации соотношения сторон ширины / высоты перед загрузкой изображений.

Кроме того, я не вижу хорошего решения, чтобы все это выглядело хорошо (без прыжков).

...