Horizontal collection view has space above cell. How to remove it? - ios

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

Related

Dragging cell outside of UICollectionView frame changes its contentOffset

There's this bug happening when I drag a UICollectionViewCell outside of the frame of the collection: the collection's contentOffset is reset to 0, I suppose to scroll to top, even when dragging the cell over below the collection. The problem is the contentOffset has to be manually put back to where it was before and that's visually delayed.
I've tried locking the scroll while dragging, such as the following
- (void)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout willBeginDraggingItemAtIndexPath:(NSIndexPath *)indexPath {
collectionView.scrollEnabled = NO;
}
- (void)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout didEndDraggingItemAtIndexPath:(NSIndexPath *)indexPath {
collectionView.scrollEnabled = YES;
}
and it didn't do anything, contentOffset still changes. Also did the following
- (CGPoint)collectionView:(UICollectionView *)collectionView targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset {
if (proposedContentOffset.y > -10.0f) { // Minimum scroll from top is -10
return CGPointMake(proposedContentOffset.x, -10.0f);
}
return proposedContentOffset;
}
- (void)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout willEndDraggingItemAtIndexPath:(NSIndexPath *)indexPath {
if (collectionView.contentOffset.y > -10.0f) { // Minimum scroll from top is -10
[collectionView setContentOffset:CGPointMake(collectionView.contentOffset.x, -10.0f)];
}
}
to reset the contentOffset whenever it changes and this works fine, but the contentOffset is changed while dragging and the reset only happens when the user releases the cell, so there's a delay. Can I, somehow, lock the contentOffset while dragging?
I think it's worth mentioning my view structure is currently
UIScrollView
UICollectionView
UICollectionView (the one that has drag-drop enabled)
The parent ScrollView unifies both scrolls of the collections inside, so that could be a problem. When the collection is scrolled to top by the contentOffset, it slightly invades the collection above it.
I realised the project was using the LXReorderableCollectionViewFlowLayout framework for drag and drop on UICollectionViews, so I inspected that source code and found that the method that treats dragging out of the collection is
- (void)handleScroll:(NSTimer *)timer
so I added a little check on case LXScrollingDirectionUp to have a maximum edge offset, that I set as a property of that class, like the following
// distance calculated above: how much to scroll based on drag action
if (distance + contentOffset.y > _maxScrollingEdgeOffset.top) {
distance = 0;
}
And that fixed it!

UICollectionView two rows on each scroll page

I'm trying to achieve such effect using Collection View :
UICollectionView image
Width of these cells should auto resize to width of the screen. Heights of each cell should be like 45% (10% is for this black gap). I tried a lot of combinations but I cannot achieve this in any way. Thank's in advance for any help.
Best regards,
Adrian.
Set the collectionView width to full screen. Implement these delegate method
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(collectionView.bounds.size.width, height);
}
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{
return UIEdgeInsetsMake(0, 0, bottom, 0);
}
I have attached an image here
I have taken a CollectionView Cell fitting the size of the width of the screen and half the size of the screen, taken a UIView and dropped it inside the collection view cell with a padding of 10-15 px from the bottom, clear the colour of the collection view background and that should give u the illusion of the CollectionViewCell cells having a padding to each other.
Whatever elements you want to show in the CollectionView Please add it to the view inside the view inside the CollectionViewCell cell

setting UICollectionViewCell to fit CollectionView

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

UICollectionView, simply fit cell to width?

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

UICollectionViewCell size and rotation

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;
}

Resources