Почему 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.
Обратите внимание также, что контроллер представления коллекции в моем примере находится в контроллере навигации, и хотя это не выглядит особенно необходимым в этом примере, в моем реальном случае мне нужен вид коллекции в контроллере навигации.
Ответы
Ответ 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))
}
Я надеюсь, что это помогает!