Friday, 23 August 2013

Adjust UICollectionViewFlowLayout When UICollectionView Frame Changes

Adjust UICollectionViewFlowLayout When UICollectionView Frame Changes

I have a UICollectionView that I created programmatically, along with its
UICollectionViewFlowLayout. The code for this looks like:
- (UICollectionView *)createCollectionToDisplayContent:(NSArray *)array
ViewWithCellIdentifier:(NSString *)cellIdentifier ofWidth:(CGFloat)width
withHeight:(CGFloat)height forEmailView:(EmailView *)emailView
{
CGFloat minInterItemSpacing;
if (!self.orientationIsLandscape) minInterItemSpacing = 9.0f;
else minInterItemSpacing = 20.0f;
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout
alloc]init];
layout.itemSize = CGSizeMake(220.0f, 45.0f);
layout.sectionInset = UIEdgeInsetsMake(5.0f, 0.0f, 5.0f, 0.0f);
layout.minimumLineSpacing = 10.0f;
layout.minimumInteritemSpacing = minInterItemSpacing;
//get pointer to layout so I can change it later
emailView.personLabelsLayout = layout;
UICollectionView *collectionView = [[UICollectionView
alloc]initWithFrame:CGRectMake(40, 4, width, height)
collectionViewLayout:layout];
collectionView.dataSource = emailView;
collectionView.delegate = emailView;
collectionView.scrollEnabled = NO;
collectionView.userInteractionEnabled = YES;
collectionView.backgroundColor = [UIColor clearColor];
[collectionView registerClass:[UICollectionViewCell class]
forCellWithReuseIdentifier:cellIdentifier];
collectionView.autoresizingMask = (UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleBottomMargin);
[collectionView reloadData];
return collectionView;
}
This code works fine to initially display the collection view. My issue is
in trying to change the flow layout when the device is rotated. I handle
the change in the collection view frame using struts and springs (see
above), and in the willAnimateRotationToInterfaceOrientation method, I
adjust the minimumInterItemSpacing property of the flow layout, and
finally call reload data on the collection view. Here is the code for
that:
-
(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration
{
CGFloat minInterItemSpacing;
if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
minInterItemSpacing = 20.0f;
} else {
minInterItemSpacing = 9.0f;
}
self.visibleEmailView = //...more code
self.visibleEmailView.personLabelsLayout.minimumInteritemSpacing =
minInterItemSpacing;
[self.visibleEmailView.personLabelsCollectionView reloadData];
//other stuff...
}
Ultimately, the flow layout should adjust dramatically when the view is
rotated: in terms of the minimumInterItemSpacing but also in terms of the
number of columns it displays. However, the layout is not adjusting as I
would expect. I am having trouble figuring out what exactly is even
happening. It looks like the minimumInterItemSpacing is not being reset on
rotation, and it looks like for each cell, the same cell is being drawn
over itself multiple times. Also, I'm getting crashes that say:
"the collection view's data source did not return a valid cell from
-collectionView:cellForItemAtIndexPath: for index path <NSIndexPath
0x9be47e0> 2 indexes [0, 6]"
In trying to begin to narrow down what is going on here, I am wondering if
anyone can tell me if my approach is correct, and/or if there is an
obvious error in my code that might be causing some or all of this funky
behavior.

No comments:

Post a Comment