UICollectionView autosizing cells break UICollectionViewFlowLayout settings - ios

I'm currently working on autosizing cells which are new in iOS8.
According to WWDC 2014 video 'What's New in Table and Collection Views', all that is required to autosize cells is to set an estimatedSize on the UICollectionViewFlowLayout given to the UICollectionView on initialisation, and override the sizeThatFits: method in the UICollectionViewCell.
Initialisation:
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setEstimatedItemSize:CGSizeMake(146.0f, 156.0f)];
_collectionView = [[UICollectionView alloc] initWithFrame:[_containerView bounds] collectionViewLayout:flowLayout];
sizeThatFits method in my cell, where _userLabel is the label that is on the bottom and marks the actual height.
- (CGSize)sizeThatFits:(CGSize)size
{
CGSize actualSize = CGSizeMake([[self contentView] bounds].size.width, [_userLabel frame].origin.x + [_userLabel bounds].size.height);
return actualSize;
}
It turns out that actual size has larger height than my estimated size, which should be okay and the cell actually gets resized properly in height.
Now with the iPhone6 and 6+, the width can also differ. I want the cells to properly span the width of the screen. I've therefore implemented three delegate methods on UICollectionViewFlowLayout; my first intuition is to calculate the width I want the cells to have according to the screen width, the section insets and the inter-item spacing.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
UIEdgeInsets sectionInsets = [self collectionView:collectionView layout:collectionViewLayout insetForSectionAtIndex:[indexPath section]];
CGFloat interItemSpacing = [(UICollectionViewFlowLayout *) collectionViewLayout minimumInteritemSpacing];
CGFloat cellWidth = ([_collectionView bounds].size.width - sectionInsets.left - sectionInsets.right - interItemSpacing) / 2;
CGSize collectionViewCellSize = CGSizeMake(cellWidth, 156.0f);
return collectionViewCellSize;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 12.0f;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(10.0f, 10.0f, 10.0f, 10.0f);
}
It works, however partly. The collectionView won't respect the top section inset, and when scrolling the collectionView, switching out another tab and then back again, cells seem to have disappeared.
Apparently I'm doing something wrong, but I can't seem to figure out where. Anyone got a clue?

Related

UICollectionViewCell remove space with animation while scrolling

I have an issue with UICollectionViewCell design layout. I need to remove space with animation while scrolling between UICollectionView Cell, I have try some delegate method of UICollectionView like -
CollectionView - minimumLineSpacingForSectionAtIndex
CollectionView - minimumInteritemSpacingForSectionAtIndex
UIEdgeInsetsMake(0,0,0,0);
scrollViewDidEndDragging
but unable to up to the mark. here is the code:
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;
float cellWidth = screenWidth / 2.1; //Replace the divisor with the column count requirement. Make sure to have it in float.
CGSize size = CGSizeMake(cellWidth, cellWidth);
return size;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 1.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 1.0;
}
// Layout: Set Edges
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0,0,0,0); // top, left, bottom, right
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
UIEdgeInsetsMake(0,0,0,0); // after scroll cell space not remove.
}
I didn't completely understand what you're trying to do, but if you want to change layout attributes of a collection view and animate the change, the best way is calling setLayout:animated:.
So like this -
UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout alloc] init];
layout.minimumLineSpacing = 1.0;
layout.minimumInteritemSpacing = 1.0;
layout.itemSize = CGSizeMake(cellWidth, cellHeight);
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:frame collectionViewLayout:layout]
And then whenever you want to change it, just call the setLayout:animated: method:
UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout alloc] init];
initialLayout.minimumLineSpacing = 5.0;
initialLayout.minimumInteritemSpacing = 7.0;
layout.itemSize = CGSizeMake(newCellWidth, newCellHeight);
[collectionView setLayout:layout animated:YES];

Error in rounding off floating point value for collection view

I want to get rid of one pixel issue on my device.I am designing a calendar which looks like below
I am using a UICollectionViewCell for this purpose
- (UIEdgeInsets)collectionView:
(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0,0,0,0); // top, left, bottom, right
}
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat collectionViewWidth = (CGRectGetWidth(collectionView.frame) / 7);
CGFloat collectionViewHeight = 48;
return CGSizeMake(collectionViewWidth, collectionViewHeight);
}
The problem is that if I increase width even by 0.0000001 point then the number of cells draw per line is 6 instead of 7. I have tried increasing the UIEdgeInset (by 0.00001) as well but it's the same issue. The properties for flow layout are set appropriately.
layout.minimumInteritemSpacing = 0.0f;
layout.minimumLineSpacing = 0.0f;
How do I make cell size consistent without leaving the gap ? The actual width of the cell is 53.571428571428569 (375/7). If I round the value to 53.58 then I get the below view
This is a very popular problem, the fastest way to resolve it use collectionViewWidth % 7 == 0 for cell size
For example your collectionViewWidth == 320. Cell == 320/7 == 45.7142857, U simply should use collectionViewWidth == 322, and your problem are resolved, because cell == 46
That the increase wasn't noticeable collectionViewWidth U have two option
First, if you collectionViewWidth == screenWidth, simply align to the center and edges will hide out of screen limits
Second if you collectionViewWidth < screenWidth, use UIview to container for collectionView, and use clipTobounds, edges will hide out of container limits.
To get rid of one pixel try using these delegate methods of UICollectionView:
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return -0.5;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return -0.5;
}
or, alternatively:
layout.minimumInteritemSpacing = -0.5;
layout.minimumLineSpacing = -0.5;
It may happen that you would have to set one of these to 0.0, while the other to -0.5. Try playing with it.

How to remove Space between Collection View Cell in ios in Iphone 6 and iPhone 6plus?

i have simple CollectionView but it works well in iphone 4 and 5 and 5s. but when i run in to iphone 6 and 6plus it look like
but i want to remove space between cell in iphone 6 and 6 plus . is it property for remove space ?? if is it property pls tell me.
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
float width = collectionView.frame.size.width / 2;
return CGSizeMake(width, width);
}
for Swift
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
{
return CGSizeMake(collectionView.frame.size.width/2, collectionView.frame.size.width/2)
}
Looks like you need to resize the cells in order to make them fill the empty space. You need to use UICollectionViewFlowLayout and the UICollectionViewFLowLayoutDelegate and implement
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(HEIGHT, SCREEN_WIDTH/2)
}
Check out the Ray Wenderlich Tutorial for more information:
http://www.raywenderlich.com/22324/beginning-uicollectionview-in-ios-6-part-12][1]
Increase dynamic width for every device using sizeForItemAtIndexPath delegate method
You Calculate width including space between two photos.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake((collectionView.frame.size.width-15)/2, (collectionView.frame.size.width-15)/2); // here 5 padding between two photos, you give hight and width here
}
CGFloat margin = 5.0;
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(([UIScreen mainScreen].bounds.size.width - margin)/ 2, ([UIScreen mainScreen].bounds.size.width - margin)/ 2);
layout.minimumLineSpacing = margin;
layout.minimumInteritemSpacing = margin;
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:[UIScreen mainScreen].bounds collectionViewLayout:layout];
Edit margin to change the space between two cells.

The behavior of the UICollectionViewFlowLayout is not defined

I've got a collection view that's set up as a single horizontal row of cells. It's throwing the following constraint error (I'm using AutoLayout):
The behavior of the UICollectionViewFlowLayout is not defined because the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.
I've Googled around and looked on SO, and everyone suggests that it's fixed by simply overriding the UIScrollViewDelegate methods:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
// iPhone 6+ device width handler
CGFloat multiplier = (screenWidth > kNumberOfCellsWidthThreshold) ? 4 : 3;
CGFloat size = screenWidth / multiplier;
return CGSizeMake(size, size);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
But it's still not working. It appears to be gawking at the fact that the cell height is taller than it's container, even though I'm setting the cell to the same hight as the container. Here's the rest of the error:
The relevant UICollectionViewFlowLayout instance is UICollectionViewFlowLayout: 0x7fa6943e7760, and it is attached to MyCollectionView: 0x7fa69581f200; baseClass = UICollectionView;
frame = (0 0; 375 98); clipsToBounds = YES; autoresize = RM+BM;
layer = CALayer: 0x7fa694315a60; contentOffset: {0, 0}; contentSize: {0, 134}
Setting the cell manually to a drastically smaller size (e.g. size - 50.0 seems to work, but why can't I set the cell size to the same height as its container?
Turns out the missing piece from my question was the fact that this UICollectionView is nested inside a UITableView. iOS 8 introduced layoutMargins in place of content offset values.
Per this question: iOS 8 UITableView separator inset 0 not working
I had to override my containing table view's cell margins:
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
// Remove seperator inset
if ([cell respondsToSelector:#selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];
}
// Prevent the cell from inheriting the Table View's margin settings
if ([cell respondsToSelector:#selector(setPreservesSuperviewLayoutMargins:)]) {
[cell setPreservesSuperviewLayoutMargins:NO];
}
// Explictly set your cell's layout margins
if ([cell respondsToSelector:#selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];
}
}
swift for override cell
override func awakeFromNib() {
super.awakeFromNib()
self.separatorInset = .zero
self.preservesSuperviewLayoutMargins = false
self.layoutMargins = .zero
}

iOS UICollection View layout doesn't work

I have a problem with iOS UICollectionView.
I have a UICollectionView with a layout:
UICollectionViewFlowLayout *collectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
collectionViewFlowLayout.itemSize = CGSizeMake(COLLECTION_VIEW_CELL_WIDTH, COLLECTION_VIEW_CELL_HEIGHT);
collectionViewFlowLayout.minimumLineSpacing = 3.0f;
My UICollectionView frame is frame = (0 ,45, 769,307);
Also, I have a custom UICollectionViewCell with frame frame = (0 ,0, 190, 100)
190 * 4 = 760. That means, that 4 cells should fit into my collection view width. But there is only 3 of them...
Where is my problem?
you can try this delegate
#pragma mark collection view cell paddings
- (UIEdgeInsets)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(0, 0, 0, 0); // top, left, bottom, right
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 0.0;
}

Resources