Предотвращение использования sizeForItemAt неправильного размера ячейки из-за повторного использования для динамической ячейки collectionView

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

В моем sizeForItemAt у меня есть следующее:

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        if let cachedSize = cachedHeightForIndexPath[indexPath] {
            return cachedSize
        }

        if let cell = collectionView.cellForItem(at: indexPath) {
            cell.setNeedsLayout()
            cell.layoutIfNeeded()
            let size = cell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
            cachedHeightForIndexPath[indexPath] = size
            print("value is \(size) for indexpath: \(indexPath)")
            return size
        }
        return CGSize(width: ScreenSize.width, height: 0.0)
    }

У меня есть три сеанса, в первом разделе высота всей ячейки теоретически равна 88, а во всех остальных разделах высота всей ячейки равна 104.

Изначально виден только первый раздел. Из консоли я вижу, что высота ячейки установлена ​​на 88,0, как и ожидалось. Когда я прокручиваю до оставшихся разделов (первый раздел будет невидимым, а ячейки будут использоваться повторно), некоторые ячейки из второго и третьего разделов используют значение 88,0 в качестве высоты ячеек при первой прокрутке для просмотра порта вместо 104. , По мере того, как я продолжаю прокручивать, ячейка неправильного размера будет использовать 104 в качестве размера. Как заставить все ячейки пересчитывать высоту и не использовать высоту из старой ячейки.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
667
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

У вас есть правильная идея, но когда вы измеряете ячейку по ее внутренним ограничениям, вызывая systemLayoutSizeFitting, вместо вызова systemLayoutSizeFitting для ячейки существующий (collectionView.cellForItem), вам нужно вооружиться ячейкой модель, которую вы настраиваете так же, как cellForItem настроил бы его и измерьте это.

Вот как я это делаю (удивительно похоже на то, что у вас есть, с одним отличием; кроме того, я сохраняю размер в модели):

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let memosize = self.sections[indexPath.section].itemData[indexPath.row].size
    if memosize != .zero {
        return memosize
    }
    self.configure(self.modelCell, forIndexPath:indexPath) // in common with cellForItem
    var sz = self.modelCell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
    sz.width = ceil(sz.width); sz.height = ceil(sz.height)
    self.sections[indexPath.section].itemData[indexPath.row].size = sz // memoize
    return sz
}

Понятно, но как бы вы инициализировали modelCell, поскольку ячейка модели не является фактической ячейкой?

kesong 30.05.2019 01:45

Невозможно получить правильное измерение для повторно используемой ячейки даже после заполнения всех данных?

kesong 30.05.2019 01:46

Как узнать, что данные уже заполнены? Вы не должны делать никаких предположений о том, что когдаsizeForItem будет вызываться для любой конкретной ячейки/элемента. Предположения, которые вы уже делаете, являются причиной ваших проблем! Я говорю вам, как перестать их делать.

matt 30.05.2019 01:49

Чтобы создать ячейку модели, вам нужно дублировать всю логику настройки представления, например, то, что находится в реальной ячейке, чтобы правильно ее настроить? Как будто это представление, но его нельзя использовать повторно.

kesong 30.05.2019 02:01

Другие вопросы по теме