UICollectionView sizeForItemAt вызывается, но имеет неправильный размер

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

Я пытался использовать UICollectionViewDelegateFlowLayout и функцию делегата sizeForItemAt для установки размеров ячеек, но они не соответствуют заданным размерам, даже если функция вызывается.

В настоящее время я устанавливаю вставки разделов, а затем вычисляю оставшуюся доступную ширину для ячеек в границах представления коллекции, после чего я делю ширину на количество ячеек в строке.

class HomeCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

    let sectionInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)

    override func viewDidLoad() {
        super.viewDidLoad()

        self.collectionView?.contentInsetAdjustmentBehavior = .always
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
        return CGSize(width: collectionView.frame.width, height: 44)
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return self.sectionInsets
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return self.sectionInsets.left
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        var numberOfItemsPerRow: CGFloat = 1
        var height: CGFloat = 0

        switch indexPath.section {
        case 0:
            numberOfItemsPerRow = 1
            height = 97
        case 1:
            numberOfItemsPerRow = 2
            height = 126
        default:
            break
        }

        let padding = self.sectionInsets.left * (numberOfItemsPerRow + 1)
        let availableWidth = collectionView.bounds.size.width - padding
        let width = availableWidth / numberOfItemsPerRow

        return CGSize(width: width, height: height)
    }
}

Это приводит к неправильному размеру ячеек, как показано на следующем рисунке. Неверный пример изображения

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

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

Чтобы завершить мою проблему, ячейки первого раздела всегда должны занимать 100% доступной ширины. Если возможно, было бы очень хорошо, если бы у них была автоматическая высота. Я пытался использовать UICollectionViewFlowLayout.automaticSize.height, но не думаю, что это сработает. Для второй секции она всегда должна занимать 50% доступной ширины.


person Nicholas Bastarache    schedule 08.10.2019    source источник


Ответы (2)


Если вы используете Storyboard для создания CollectionView.

Я думал, что должен invalidateLayout(). Оказывается, в iOS 13 есть странная ошибка.

вам нужно создать свой собственный UICollectionViewFlowLayout. Назовите что-то подобное в своем viewDidLoad()


        collectionView.collectionViewLayout = {
            let flowLayout = UICollectionViewFlowLayout()
            flowLayout.scrollDirection = .horizontal
            return flowLayout
        }()
person blyscuit    schedule 27.06.2020
comment
Наверняка вы имеете в виду iOS 13, верно? ;) Но да, это сделало это для моей консоли предупреждений UICollectionViewFlowLayoutBreakForInvalidSizes. - person Ivan; 07.07.2020
comment
Ничего страшного, было ясно, что имелось в виду. Просто дал отзыв для других, читающих ветку. Ваше здоровье. - person Ivan; 29.07.2020

Вы должны аннулировать макет на viewDidLayoutSubviews, чтобы пересчитать размеры ячеек. Я прикрепил фрагмент кода. Попробуй это

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews() 
    collectionView.collectionViewLayout.invalidateLayout()
}
person bohdans    schedule 08.10.2019
comment
Вызывает бесконечный цикл, когда я добавляю это в свой UICollectionViewController на iOS 13.1. - person Zandor Smith; 17.03.2020
comment
это сделало работу для меня. пришлось вставить его в класс расширения - person dhir; 09.05.2021