Подтвердить что ты не робот

Почему UICollectionView регистрирует ошибку, когда ячейки полноэкранные?

У меня есть UICollectionViewController с помощью UICollectionViewFlowLayout, где my itemSize является размером UICollectionView. В принципе, это макет строки ячеек, где каждая ячейка является полноэкранным и прокручивает по горизонтали.

В моем подклассе UICollectionViewFlowLayout я переопределил prepareLayout следующим образом:

- (void)prepareLayout {
    self.itemSize = self.collectionView.frame.size;
    self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    self.collectionView.pagingEnabled = YES;
    self.minimumLineSpacing = 0.0;
    self.minimumInteritemSpacing = 0.0;
    self.sectionInset = UIEdgeInsetsZero;
    self.footerReferenceSize = CGSizeZero;
    self.headerReferenceSize = CGSizeZero;
}

UICollectionViewController - это очень простой способ вернуть 10 элементов в один раздел. Я включил образец проекта на GitHub для более подробной информации.

Кажется, все настроено правильно. Он выглядит правильно в симуляторе и на устройстве, но, когда отображается представление коллекции, в консоль входит ошибка:

the behavior of the UICollectionViewFlowLayout is not defined because:
the item height must be less that the height of the UICollectionView minus the section insets top and bottom values.

Обратите внимание также, что контроллер представления коллекции в моем примере находится в контроллере навигации, и хотя это не выглядит особенно необходимым в этом примере, в моем реальном случае мне нужен вид коллекции в контроллере навигации.

4b9b3361

Ответ 1

В UIViewController - automaticallyAdjustsScrollViewInsets есть свойство, которое по умолчанию имеет значение YES. Это означает, что когда a UIViewController имеет UIScrollView в своей иерархии представлений, что справедливо для свойства UICollectionViewController -the contentInset этого прокрутки, автоматически настраивается для учета областей экрана, потребляемых в строке состояния, панель навигации, панель инструментов или панель вкладок.

В документации для этого свойства указано:

автоматическиAdjustsScrollViewInsets

Указывает, должен ли контроллер просмотра автоматически настраивать свои вставки прокрутки.

@property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets

Обсуждение

Значение по умолчанию - YES, что позволяет контроллеру просмотра настраивать свои вставки прокрутки в ответ на области экрана, используемые в строке состояния, панели навигации, панели инструментов или панели вкладок. Установите значение НЕТ, если вы хотите самостоятельно управлять настройками вставки прокрутки, например когда в иерархии представлений имеется более одного вида прокрутки.

Решение состоит в том, чтобы установить automaticallyAdjustsScrollViewInsets в NO где-то в вашем подклассе UICollectionViewController, например, в viewDidLoad:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.automaticallyAdjustsScrollViewInsets = NO;
}

Я привел пример пример проекта на GitHub, который иллюстрирует эту проблему и решение. Есть две ветки: with_error и fixed_error. Ниже приведен диалог изменения в GitHub.

Ответ 2

Эта проблема возникла только для меня на 3-х экранах (а именно iPhone 6 Plus.) Как оказалось, автозапуск не очень понравился бесконечным значениям с плавающей запятой (например,.33333333), поэтому мое решение было floor высота возврата в sizeForItemAt:indexPath:.

return CGSize(width: preferredWidth, height: floor(preferredHeight))

Ответ 3

Обновление iOS 11: automaticallyAdjustsScrollViewInsets AdjustsScrollViewInsets устарела в iOS 11.0.

Apple рекомендует вместо этого использовать метод UIScrollView contentInsetAdjustmentBehavior. Я установил это значение на .never и ошибка исчезла. Вы также можете установить это свойство в Интерфейсном Разработчике.

Ответ 4

Я столкнулся с этой проблемой при повороте устройства из портретной в альбомную, обратно в портретную. Вы хотите сделать недействительным макет collectionView при повороте устройства и перед вызовом super, например:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    // Causes collection view cells to be resized upon orientation change.
    // Important that this is called *before* call to super in order to prevent error from being logged to console.
    [self.collectionView.collectionViewLayout invalidateLayout];

    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];

    //...
}

Ответ 5

ios 10: верхний вид не был подключен к выходу

Ответ 6

Как и у Stunner, у меня была такая же проблема при повороте из альбомной ориентации (изображение с использованием полной ширины) в портретный режим. Его предложение было единственным, которое действительно помогло.

Прикрепленный код с последним Swift для его примера ObjC... и в качестве бонуса, мой код, чтобы найти центральную ячейку представления коллекции. Работает довольно хорошо ;-)

/**
 -----------------------------------------------------------------------------------------------

 viewWillTransition()

 -----------------------------------------------------------------------------------------------
 */
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {

    // find cell in the center of the screen and store it in a global variable
    let center = self.view.convert((self.collectionView!.center), to: self.collectionView)

    // get the indexPath for the cell in the center of the current screen
    if let index = collectionView!.indexPathForItem(at: center) {

        // store it in a class property
        self.indexPathOfCenterCell = index
    }

    // force recalculation of margins, borders, cell sizes etc.
    self.collectionView?.collectionViewLayout.invalidateLayout()

    // inform UIKit about it    
    super.viewWillTransition(to: size, with: coordinator)
}

Ответ 7

У меня была похожая проблема.

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

чтобы исправить это

я использовал

   func updateHeightPerRatio(with image:UIImage) {
    let ratio = collectionView.bounds.width / image.size.width
    constHeightCollectionView .constant =  ceil(image.size.height * ratio)
    collectionView.reloadData()
    collectionView.performBatchUpdates({
        collectionView.layoutIfNeeded()
    }) { (completed) in
        self.collectionView.reloadData()
        self.layoutIfNeeded()
    }
}

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

И теперь нет журнала для выпуска сейчас.

Надеюсь, это полезно

Ответ 8

Этот способ отлично сработал для меня!

Я просто вычел верхнюю и нижнюю вставки из высоты обзора, как сказано в этой ошибке.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: view.frame.width , height: view.frame.height - (view.safeAreaInsets.top + view.safeAreaInsets.bottom)) }

Я надеюсь, что это помогает!