I have a UICollectionViewController
using a UICollectionViewFlowLayout
where my itemSize
is the size of the UICollectionView
. Basically, this is a line layout of cells where each cell is fullscreen and scrolls horizontally.
In my UICollectionViewFlowLayout
subclass, I have overridden prepareLayout
as follows:
- (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; }
The UICollectionViewController
is very basic returning 10 items in one section. I've included a sample project on GitHub for more detail.
Everything appears to be set up correctly. It looks right in the simulator and on the device but, when the collection view is displayed, there is an error logged to the console:
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.
Note also that the collection view controller in my example is in a navigation controller and while that doesn't look particularly necessary in the example, in my real-world case I need the collection view in a navigation controller.
The collection view presents items onscreen using a cell, which is an instance of the UICollectionViewCell class that your data source configures and provides. In addition to its cells, a collection view can present data using other types of views.
Overview. A flow layout is a type of collection view layout. Items in the collection view flow from one row or column (depending on the scrolling direction) to the next, with each row containing as many cells as will fit. Cells can be the same sizes or different sizes.
There is a property on UIViewController
–automaticallyAdjustsScrollViewInsets
–that defaults to YES
. This means that when a UIViewController
has a UIScrollView
in its view hierarchy–which is true of a UICollectionViewController
–the contentInset
property of that scroll view is adjusted automatically to account for screen areas consumed by the status bar, navigation bar, and toolbar or tab bar.
The documentation for that property states:
automaticallyAdjustsScrollViewInsets
Specifies whether or not the view controller should automatically adjust its scroll view insets.
@property(nonatomic, assign) BOOL automaticallyAdjustsScrollViewInsets
Discussion
Default value is YES, which allows the view controller to adjust its scroll view insets in response to the screen areas consumed by the status bar, navigation bar, and toolbar or tab bar. Set to NO if you want to manage scroll view inset adjustments yourself, such as when there is more than one scroll view in the view hierarchy.
The solution is to set automaticallyAdjustsScrollViewInsets
to NO
somewhere in your UICollectionViewController
subclass, such as in viewDidLoad
:
- (void)viewDidLoad { [super viewDidLoad]; self.automaticallyAdjustsScrollViewInsets = NO; }
I have put an example project on GitHub that illustrates this problem and solution. There are two branches: with_error
and fixed_error
. Here is a diff of the change on GitHub.
This issue just occured to me on 3x screens (namely the iPhone 6 Plus.) As it turned out, the autolayout engine did not really like infinite floating point values (such as .33333333), so my solution was to floor
the return height in sizeForItemAt:indexPath:
.
return CGSize(width: preferredWidth, height: floor(preferredHeight))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With