I'm trying to display pictures in a collection view, 1 picture at a time and allow them to be scrolled horizontally.
so i was hoping to have the cell fit the size of the collection view, perhaps with a bit of margin.
I've tried to do it by setting the cell frame to the same as the collection view's frame
CGRect containerFrame = self.photoCollectionView.frame;
cell.frame = CGRectMake(containerFrame.origin.x, containerFrame.origin.y, containerFrame.size.width, containerFrame.size.height);
but the cell just disappears all together.
Is there a standard way to do it?
Take a look at the UICollectionViewFlowLayout Class Reference. You should use UICollectionViewDelegateFlowLayout.
Implement this method to change the size of cells
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
and to change the spacing between cells
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
Related
I have collection view with cells I'm presenting horizontally + paging enabled. However I have above cell space that I cant remove (green on screenshot - collection view background). Size of cell is same as containers frame. For better understanding what I mean check screenshot. Any ideas? Thank you very much.
automaticallyAdjustsScrollViewInsets doesn't works for me
[self.calendarView setContentInset:UIEdgeInsetsMake(-64, 0, 0, 0)]; works but I don't know how to get these -64 programatically.
Did you try to implement these methods below and set zero insets and spacings?
You also need to check if the size of the cell is appropriate, may be the way you see the top spacing is the only way layout engine can put the cell. Please, check what size is set as expected
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsZero;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
return 0.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
return 0.0;
}
I've came across similar issue many times.
When a UIScrollView or its subclass, e.g. UITableView and UICollectionView, is the first child of viewController.view, it will get a unexpected contentInset.
My solution:
If there are other siblings of UIScrollView, make one of
non-UIScrollView as first child.
If there is no other siblings, add a dummy UIView as the first child, and either hide the UIView or set the height to 0
How can I set the collection cell view to dynamically stretch to iphone screen width (e.g. iphone 5s, iphone 6 plus)?
I tried:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
(ResultCell *)[collectionView dequeueReusableCellWithReuseIdentifier:cellClass
forIndexPath:indexPath];
cell.bounds = CGRectMake(0,0, self.view.bounds.size.width, 150);
return cell;
}
That does not work. I don't see the content get stretch to the right side of the screen.
I have tried adding this delegate method:
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGSize cellSize;
cellSize.width = self.view.bounds.size.width;
// body view height
cellSize.height = 150;
return cellSize;
}
I have set breakpoints in the method, but that method never get called?
I had the same issue with the same use case. I finally ended up doing
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(collectionView.bounds.size.width, 150);
}
This changes the size of each item (cell) of the collection view. Hence you could change the size of each cell using this. Here i need the cell width to be same as of my UICollectionView so i passed the UICollectionview's width and specific height that i desired. Hope this would help.
Also there is no need to set the cell bounds in - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath as the size gets set via - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
Also make sure that you have attached the desired Delegates & DataSources to the UICollectionView
The size of the cells are specified by the layout object of the collection view. Are you using a UICollectionViewFlowLayout? Try either setting the itemSize property of the layout object or implementing the delegate method: collectionView:layout:sizeForItemAtIndexPath:
You will be able to specify the size of the item (cell) relative to the collection view's bounds there.
Keep in mind that your collection view also needs to be set up so that it resizes with your view controller. If you're using a UICollectionViewController that should be set up automatically. Otherwise, you'll have to constrain your collection view to the bounds of its superview.
Update:
You can set the itemSize property of the layout directly on the layout:
self.layout.itemSize = CGSizeMake(CGRectGetWidth(self.collectionView.bounds), 100);
or, (better if you're handling rotation or resizing), implement the appropriate delegate call back:
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(CGRectGetWidth(collectionView.bounds), 100);
}
I'd recommend reading the appropriate UICollectionView docs to get more familiar with how collection views and their layout's work:
UICollectionViewDelegateFlowLayout
UICollectionViewFlowLayout
UICollectionView Programming Guide
Here's a simple UICollectionView in yellow
The red arrow sets the width of the cell. (TBC: clicking on the pink cell: for 'size' select 'Default', then what you set at the red arrow becomes the size of the cell.)
Example, for an upright iPhone set width to 320.
But this seems crazy ... surely I can set the cell width based on the width of the UICollectionView?
There's no problem autosizing the view itself ..
That works fine.
But it seems crazy that I can't set the width of the CELL to be "same as the view". It seems hard to believe one has to set it manually, in code?
TBC In other words, as Nikita points out,
-(CGSize) collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return self.view.frame.size;
}
(indeed you also typically need this ...)
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
insetForSectionAtIndex:(NSInteger)section
{
return UIEdgeInsetsMake(0,0,0,0); //t,l,b,r
}
In fact - you have to do that in code?! There's no way to do that in Storyboard, with autolayout, or anything else?!
I think you need to take a look at
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
of UICollectionViewLayout where you can set size based on orientation and current frame.
It would indeed seem that you simply have to do this in code.
There is a simple way to do this. Here is the swift code. Assumes you want one item wide and in the example my cells are 64 pts high, and I want 8 pts for side margins, and finally collectionView is the name of your UICollectionView.
Insert this into viewDidLoad :
let layout = collectionView?.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize.init(width: (UIScreen.main.bounds.width - 16), height: 64.0)
This will set all the cells to default to that size. You can still override individual cells if you subclass UICollectionViewLayout or UICollectionViewFlowLayout, as mentioned in other answers. But if you simply want to have more table view like behavior this should work.
I my case cell inset making extra shapes
In my UICollectionView I have a cell that should take the entire width of the device. Here is how I set the size for the item:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(self.view.bounds.size.width, 120);
}
I have found that on rotation, the width of the cell does not change. I can resolve this using [collectionView.collectionViewLayout invalidateLayout] in didRotateFromInterfaceOrientation: but this isn't satisfactory. What if the user rotates while in another screen in my app? I will need to add the same to viewWillAppear. What about if the rotation occurs while the app is backgrounded? Now I need to add it for the UIApplicationDidBecomeActiveNotification notification.
What confuses me most is that this is not required for my custom headers in the same collection view. The following supplementary views correctly re-size on orientation change:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
return CGSizeMake(self.view.bounds.size.width, 40);
}
Where am I going wrong? What should I do to have the cells re-size automatically to fill the width of the collection view?
A bit late I know but could you solve this by subclassing flow layout and adding?
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds {
return TRUE;
}
http://postimg.org/image/6bws3catp/
As you can see on the image I need something that gives me the possibility of resizing a cell depending on the length of the text that contains.
I' ve been trying to do that with a UICollectionview but the cells have always the same size and if I try to alterate the size playing with the frame.size and location parameters the scroll gets crazy.
Maybe the UICollectionView isn't the best choice...
Thank you very much
EDIT:
Because of your answers my cells are able to change dynamically their size but the margins aren't behaving as I expected.
The margins of the cells depends always on the biggest cell of the same row
http://postimg.org/image/3scthf9rv/
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{
return 6;
}
I have implement this to set my margin value between cells in 6 points, but maybe this only works when you have one cell in each row in a vertical collection view..
Thank you again for all your help
You can check out https://github.com/bryceredd/RFQuiltLayout . Looks
like something you can use for this...
you can override the following method and return a CGSize object that specifies the size you want to use for each cell. Using this method, you can actually have each cell be a different size:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
Example:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(100, 100);
}
Your view controller needs to be a delegate of UICollectionViewDelegateFlowLayout in order for this method to be called. So don't forget to add that delegate declaration to your view controller's .h file, such as:
#interface MyViewController () <UICollectionViewDelegateFlowLayout>
UICollectionView is the correct choice. You just need to customise the flow layout attributes.
Read Customizing the Flow Layout Attributes
Specifically you would need to implement Collection View Delegate method:
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
// In this method you can calculate the size of the string for each cell
UIFont *font = // font to create the text for each cell
NSString *string = // text string for each cell
CGSize size = [string sizeWithFont];
return size;
}