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.
Related
I'm working with a UICollectionView where I have to set a small gap between the margin and the cell of UICollectionView. I tried adjusting the inset of the flow layout like this but I couldn't get what I wanted.
let flow = resturantCollection.collectionViewLayout as! UICollectionViewFlowLayout
flow.sectionInset = UIEdgeInsetsMake(0, 10, 0, 10)
Please look at the image to get an idea of what I'm trying to do.
I'm trying to set a small gap between the cell and the margin. Is there anyway to do this?
Here is the code
//-----------------------------------------------------------------------
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake((self.view.frame.size.width - 40) / 3 , (self.view.frame.size.width - 40) / 3);
}
//-----------------------------------------------------------------------
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(10, 10, 10, 10);
}
//-----------------------------------------------------------------------
Here what i want is need 4 Cell to be displayed in Every screen with 10px space all sides
(self.view.frame.size.width - 40) / 3 -> 4 Cells
I have a problem with my UICollectionView, I have 3 columns and everything works fine instead of iphone 5 and 4.
In iphone 6 my collectionview looks that (width in cell):
Iphone 5 with cells:
The problem is, when in last row, I have 2 cells, and it looks like that:
The look I want to achieve:
Every where I can, I set insets to (0, 0, 0, 0). I use default layout with my insets set in storyboard. So is it possible to achieve this with flow layout or I need to look into custom layout?
=== edit
I create UICollectionView in storyboard and implements delegate:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
float width = self.frame.size.width / 3.0f;
float height = floorf(width + 118);
if(SMALLER_THAN_6){
width = floorf(width);
if([indexPath row] % 3 < 2){
++width;
}
}
return CGSizeMake(width, height);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0, 0, 0, 0);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 0.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
minimumLineSpacingForSectionAtIndex:(NSInteger)section{
return 0.0;
}
I solved this problem by inserting an empty cell at the end of the row (only on iphone 4 & 5)
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?
I am attempting to lay my UICollectionView out such that it is a 2x3 grid per page. Here is what I am getting so far:
As you can see, the next "page" is peeping in from the right, which I don't want. I figured if I know my width is always going to be 320pts (iPhone only), then I would want my cells to be 130pts in width with 15pts on either side.
Code for layout delegate:
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(130, 130);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(20.0f, 15.0f, 20.0f, 15.0f);
}
And also cellForItemAtIndexPath:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath{
CustCollectionViewCell *cell =
[collectionView dequeueReusableCellWithReuseIdentifier:kReuseID
forIndexPath:indexPath];
//Set up list name label
cell.LblListName.font = [self getDefaultFontWithSize:15.0f];
cell.LblListName.textColor = fontAndTertiaryColor;
cell.LblListName.textAlignment = NSTextAlignmentCenter;
cell.LblListName.text = #"Failtron";
//cell.LblListName.adjustsFontSizeToFitWidth = YES;
cell.backgroundColor = secondaryColor;
cell.parallaxIntensity = kParallaxMotion;
[Utilities createViewBorder:cell];
return cell;
}
I thought an inset would act like padding in CSS but I believe I'm off the mark with that one, I should also note that in the UIStoryboard my layout is set to flow. Please let me know if I am missing any relevant code, this is my first attempt with a UICollectionView. I would like this to scroll horizontally as well.
Ok, there are tons of ways to manipulate layouts for a UICollectionView, but sounds like since you are using "flow" you can just implement <UICollectionViewDelegateFlowLayout> in your .h and then use the following methods to tweak your layout to your liking:
#pragma mark – UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
// Size of the cell
CGSize retval = CGSizeMake(130,130);
return retval;
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
insetForSectionAtIndex:(NSInteger)section {
//top, left, bottom, right
return UIEdgeInsetsMake(0, 20, 0, 20);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
//Minimum spacing between cells
CGFloat interimSpacing = 0.0f;
return interimSpacing;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
minimumLineSpacingForSectionAtIndex:(NSInteger)section {
// Minimum spacing between lines. In your case,
this is the distance between columns
// If your scroll direction was vertical,
this would be the distance between rows
CGFloat lineSpacing = 20.0f;
return lineSpacing;
}
I've prepopulated this code with some values that should be pretty darn close to what you wanted to accomplish.
Alternatively, all of this can be done in Interface Builder by selecting the UICollectionView and adjusting the values in the Size Inspector, albeit more confusing in my opinion.
UICollectionView- How to remove spacing above first cell?
I have the top inset = 0, and lines = 10
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row == 0) {
return CGSizeMake(collectionView.width, 44);
}
return CGSizeMake(300, 150);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0, 10, 10, 10);
}
Seems it is something to do with setting the first cell to a different size
if i remove the check for row ==0 in sizeForItemAtIndexPath and return same for all cells it is flush with the top.
Any ideas?
Solution is just to write inside viewDidLoad
self.automaticallyAdjustsScrollViewInsets = NO;
I did it following way (tested on iOS7, 55 is a magic value):
#pragma mark - UICollectionViewDelegateFlowLayout
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
//-55 is a tweak value to remove top spacing
return CGSizeMake(1, -55);
}
Alternative way using your code:
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(-55, 10, 10, 10);
}
If you'd like to use Interface Builder, you can uncheck "Adjust Scroll View Insets" on the View Controller's Attribute Inspector:
Or use Amit's answer to do it programatically.
I don't think so that one is your top inset. Edit your question with some piece of code you have applied.
If it was collectionView inset then it should remove by passing 0 as top inset.
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0, 10, 10, 10);
}
And the following layout delegate used for row spacing.
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 30;
}
Using srtuct and spring set the collectionview autoresizing mask like this and also make sure you set the frame y to 0