I want to make custom UICollectionViewLayout like this.
http://i.stack.imgur.com/aWUIa.jpg
When I scroll second page image size not fit the cell sizes;
http://i.stack.imgur.com/GOUmF.jpg
And turn back first page again;
http://i.stack.imgur.com/lQQ3h.png
Image sizes and cell sizes not fit each other.
Here my custom layout code;
//
// SeyahatLayout.m
// SeyahatTrend
//
// Created by Mehmet Can Yavuz on 03.06.2013.
// Copyright (c) 2013 Mehmet Can Yavuz. All rights reserved.
//
#import "SeyahatLayout.h"
#import "SeyahatLayoutAttributes.h"
#define kNumberOfItemsPerPage 5
static NSString * const BHPhotoAlbumLayoutPhotoCellKind = #"PhotoCell";
#interface SeyahatLayout ()
#property (nonatomic, strong) NSDictionary *layoutInfo;
#end
#implementation SeyahatLayout
- (CGSize)collectionViewContentSize
{
// Ask the data source how many items there are (assume a single section)
id<UICollectionViewDataSource> dataSource = self.collectionView.dataSource;
int numberOfItems = [dataSource collectionView:self.collectionView
numberOfItemsInSection:0];
// Determine how many pages are needed
int numberOfPages = ceil((float)numberOfItems/(float)kNumberOfItemsPerPage);
// Set the size
float pageWidth = self.collectionView.frame.size.width;
float pageHeight = self.collectionView.frame.size.height;
CGSize contentSize = CGSizeMake(numberOfPages * pageWidth, pageHeight);
return contentSize;
}
#pragma mark - Layout
- (void)prepareLayout
{
NSMutableDictionary *newLayoutInfo = [NSMutableDictionary dictionary];
NSMutableDictionary *cellLayoutInfo = [NSMutableDictionary dictionary];
NSInteger sectionCount = [self.collectionView numberOfSections];
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0];
for (NSInteger section = 0; section < sectionCount; section++) {
NSInteger itemCount =
[self.collectionView numberOfItemsInSection:section];
for (NSInteger item = 0; item < itemCount; item++) {
indexPath = [NSIndexPath indexPathForItem:item inSection:section];
SeyahatLayoutAttributes* attr =
[self layoutAttributesForItemAtIndex:item];
// UICollectionViewLayoutAttributes *itemAttributes =
// [UICollectionViewLayoutAttributes
// layoutAttributesForCellWithIndexPath:indexPath];
// itemAttributes.frame = [self frameForAlbumPhotoAtIndexPath:indexPath];
[cellLayoutInfo setObject:attr forKey:indexPath];
}
}
newLayoutInfo[BHPhotoAlbumLayoutPhotoCellKind] = cellLayoutInfo;
self.layoutInfo = newLayoutInfo;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:
(NSIndexPath *)indexPath {
return self.layoutInfo[BHPhotoAlbumLayoutPhotoCellKind][indexPath];
}
-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect
{
// NSInteger itemCount = [self.collectionView numberOfItemsInSection:0];
// NSMutableArray* attributes = [NSMutableArray array];
// for (NSInteger i=0 ; i < itemCount; i++) {
// NSIndexPath* indexPath = [NSIndexPath indexPathForItem:i
inSection:0];
// [attributes addObject:
[self layoutAttributesForItemAtIndexPath:indexPath]];
// }
// return attributes;
NSLog(#"RECTX: %f",rect.origin.x );
NSLog(#"RECTY: %f",rect.origin.y );
NSLog(#"RECTWIDTH: %f",rect.size.width );
NSLog(#"RECTHEIGHT: %f",rect.size.height );
id<UICollectionViewDataSource> dataSource = self.collectionView.dataSource;
int numberOfItems = [dataSource collectionView:self.collectionView
numberOfItemsInSection:0];
NSMutableArray* attributes = [NSMutableArray array];
int page = rect.origin.x / 1024.0;
if(numberOfItems>0){
for(NSInteger i = 0; i<kNumberOfItemsPerPage; i++){
int x = page*kNumberOfItemsPerPage + i;
NSLog(#"%d",x);
NSIndexPath* indexPath = [NSIndexPath indexPathForItem:x inSection:0];
[attributes addObject:self.layoutInfo[BHPhotoAlbumLayoutPhotoCellKind]
[indexPath]];
}
return attributes;
}
else
return nil;
}
- (SeyahatLayoutAttributes *)layoutAttributesForItemAtIndex:(int)index
{
NSIndexPath *path = [NSIndexPath indexPathForItem:index inSection:0];
SeyahatLayoutAttributes *attributes =
(SeyahatLayoutAttributes *)[UICollectionViewLayoutAttributes
layoutAttributesForCellWithIndexPath:path];
// Figure out what page this item is on
int pageNumber = floor((float)index / (float) kNumberOfItemsPerPage);
// Set the horizontal offset for the start of the page
float pageWidth = self.collectionView.frame.size.width;
float horizontalOffset = pageNumber * pageWidth;
// Now, determine which position this cell occupies on the page.
int indexOnPage = index % kNumberOfItemsPerPage;
int column = 0;
switch (indexOnPage) {
case 0:
case 1:
column = 0;
break;
case 2:
case 3:
case 4:
column = 3;
break;
default:
column = 0;
break;
}
int row = 0;
switch (indexOnPage) {
case 0:
case 2:
row = 0;
break;
case 3:
row = 1;
break;
case 1:
case 4:
row = 2;
break;
default:
row = 0;
break;
}
horizontalOffset = horizontalOffset + ((175.0 + 30.0) * column) + 30.0;
float verticalOffset = (194.0 + 30.0) * row + 30.0;
// finally, determine the size of the cell.
float width = 0.0;
float height = 0.0;
switch (indexOnPage) {
case 0:
width = 585.0;
height = 418.0;
break;
case 1:
width = 585.0;
height = 194.0;
break;
default:
width = 350.0;
height = 194.0;
break;
}
CGRect frame = CGRectMake(horizontalOffset, verticalOffset, width, height);
[attributes setFrame:frame];
return attributes;
}
+ (Class)layoutAttributesClass
{
return [SeyahatLayoutAttributes class];
}
#end
Here my custom uicollectionviewcell code;
//
// SeyahatCell.m
// SeyahatTrend
//
// Created by Mehmet Can Yavuz on 03.06.2013.
// Copyright (c) 2013 Mehmet Can Yavuz. All rights reserved.
//
#import "SeyahatCell.h"
#import "PNCollectionCellBackgroundView.h"
#implementation SeyahatCell
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
//self.backgroundColor = [UIColor whiteColor];
PNCollectionCellBackgroundView* backgroundView =
[[PNCollectionCellBackgroundView alloc] initWithFrame:frame];
self.backgroundView = backgroundView;
self.imageView =
[[UIImageView alloc] initWithFrame:CGRectMake(5,
5,
frame.size.width-10,
frame.size.height-10)];
[self.contentView addSubview:self.imageView];
}
return self;
}
And my cellForItemAtIndexPath method;
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
SeyahatCell *seyahatCell =
[collectionView dequeueReusableCellWithReuseIdentifier:SeyahatCellIdentifier
forIndexPath:indexPath];
Post * p = [self.posts objectAtIndex:indexPath.row];
[seyahatCell.imageView setImage:nil];
if(p.thumbnail){
[seyahatCell.imageView setImageWithURL:[NSURL URLWithString:p.thumbnail]];
}
else{
[seyahatCell.imageView setImage:nil];
}
return seyahatCell;
}
How can i fix this problem?
Try to use existing solutions for layouts. For this purpose i prefer to use https://github.com/bryceredd/RFQuiltLayout
Related
I created a custom UICollectionViewLayout and I've put it in my Collection View Controller in the storyboard. I didn't get that much problems on displaying the items/cells. My problem is that the viewForSupplementaryElementOfKind is not being called. I can't to seem to pinpoint on why is that. I tried to go back to the default layout and it does call it then but I need my custom UICollectionViewLayout. I've left NSLogs to check and viewForSupplementaryElementOfKind is not being called.
Here is my MyCollectionViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
viewArray = [NSMutableArray array];
//setup the delegate for vertical flow layout
[(VerticalFlowLayout*)self.collectionViewLayout setDelegate:self];
//register the headers
[self.collectionView registerNib:[ButtonHeaderCollectionReusableView nib] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:[ButtonHeaderCollectionReusableView reusableID]];
//set the insets
[self.collectionView setContentInset:UIEdgeInsetsMake(23, 5, 10, 5)];
}
#pragma mark - CollectionView DataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [self.cardsArray count];
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
NSLog(#"Number of Sections");
return 1;
}
- (UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Making Card");
CardCell *card = [collectionView dequeueReusableCellWithReuseIdentifier:#"CardCell" forIndexPath:indexPath];
// UILabel *cardLabel = [card viewWithTag:101];
// [cardLabel setText:[textArray objectAtIndex:[indexPath row]]];
return card;
}
- (UICollectionReusableView*)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Making Header");
UICollectionReusableView *reusableView = nil; /*[[UICollectionReusableView alloc] initWithFrame:CGRectMake(0, 0, 100, 75)];*/
// [reusableView setBackgroundColor:[UIColor blackColor]];
if (kind == UICollectionElementKindSectionHeader) {
ButtonHeaderCollectionReusableView *headerview = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:[ButtonHeaderCollectionReusableView reusableID] forIndexPath:indexPath];
return headerview;
}
// if (kind == UICollectionElementKindSectionFooter) {
// UICollectionReusableView *footerview = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:#"FooterView" forIndexPath:indexPath];
// }
return reusableView;
}
- (CGSize)collectionView:collectionView layout:(nonnull UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section {
return CGSizeMake(180.0f, 72.0f);
}
Now here is my MyFlowLayout.m
- (id)initWithCoder:(NSCoder *)aDecoder {
NSLog(#"Vertical Flow Layout init with coder");
if(self = [super initWithCoder:aDecoder]) {
contentHeight = 0;
cachedAttributes = [NSMutableArray array];
}
return self;
}
- (void)prepareLayout {
NSLog(#"Preparing Layout");
// [super prepareLayout];
contentWidth = CGRectGetWidth(self.collectionView.bounds) - (self.collectionView.contentInset.left + self.collectionView.contentInset.right);
if([cachedAttributes count] == 0) {
//compute for column width
CGFloat columnWidth = contentWidth / NUMBER_OF_COLUMNS;
NSMutableArray *xOffsets = [NSMutableArray array];
for(int i = 0; i < NUMBER_OF_COLUMNS; i++) {
[xOffsets addObject:[NSNumber numberWithFloat:(i * columnWidth)]];
}
//compute for height
NSMutableArray *yOffsets = [NSMutableArray array];
for(int i = 0; i < NUMBER_OF_COLUMNS; i++) {
[yOffsets addObject:[NSNumber numberWithFloat:75]];
}
int column = 0;
//loop through all the sections and items in the collectionview
for(int i = 0; i < self.collectionView.numberOfSections; i++) {
for(int j = 0; j < [self.collectionView numberOfItemsInSection:i]; j++) {
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:j inSection:i];
//time to do some frame calculation
///let's start with the width
CGFloat width = columnWidth - CELL_PADDING * 2;
///then the height
CGFloat viewHeight = [self.delegate getViewHeightWithCollectionView:self.collectionView indexPath:indexPath withWidth:width];
CGFloat height = CELL_PADDING + viewHeight + /*textHeight +*/ CELL_PADDING;
CGFloat xOffset = [[xOffsets objectAtIndex:column] floatValue];
CGFloat yOffset = [[yOffsets objectAtIndex:column] floatValue];
CGRect frame = CGRectMake(xOffset, yOffset, columnWidth, height);
CGRect insetFrame = CGRectInset(frame, CELL_PADDING, CELL_PADDING);
//now that computation is done we shall make the attributes
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
[attributes setFrame:insetFrame];
[cachedAttributes addObject:attributes];
//time to increment the height and the column
contentHeight = MAX(contentHeight, CGRectGetMaxY(frame));
NSNumber *yOffSetColumn = [yOffsets objectAtIndex:column];
yOffSetColumn = [NSNumber numberWithFloat:([yOffSetColumn floatValue] + height)];
[yOffsets replaceObjectAtIndex:column withObject:yOffSetColumn];
NSLog(#"Content Height: %f yOffSetColumn: %# == %#", contentHeight, yOffSetColumn, [yOffsets objectAtIndex:column]);
column = column >= (NUMBER_OF_COLUMNS - 1) ? 0 : ++column;
}
}
}
}
- (CGSize)collectionViewContentSize {
// NSLog(#"Collection View Content Size");
return CGSizeMake(contentWidth, contentHeight + 75);
}
// called after preparelayout to determine which items are visible in the given rect
- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {
NSMutableArray<UICollectionViewLayoutAttributes *> *layoutAttributes = [NSMutableArray array];
NSInteger sectionsCount = [self.collectionView.dataSource numberOfSectionsInCollectionView:self.collectionView];
NSLog(#"Sections count: %ld", (long)sectionsCount);
for(int i = 0; i < sectionsCount; i++) {
//for header
UICollectionViewLayoutAttributes *headerAttributes = [self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:[NSIndexPath indexPathForItem:0 inSection:i]];
// if(CGRectIntersectsRect(headerAttributes.frame, rect)) {
// NSLog(#"Adding Section Attribute");
[layoutAttributes addObject:headerAttributes];
// }
for (UICollectionViewLayoutAttributes *attributes in cachedAttributes) {
if(CGRectIntersectsRect(attributes.frame, rect)) {
[layoutAttributes addObject:attributes];
}
}
// NSInteger itemsCount = [self.collectionView numberOfItemsInSection:i];
// for(int j = 0; j < itemsCount; j++) {
// UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:j inSection:i]];
// if(CGRectIntersectsRect(attributes.frame, rect)) {
// [layoutAttributes addObject:attributes];
// }
// }
}
return layoutAttributes;
}
//- (UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
// NSLog(#"Layout Attributes For Item: %ld %ld", [indexPath row], [indexPath section]);
//
// UICollectionViewLayoutAttributes *attributes = [cachedAttributes objectAtIndex:[indexPath row]];
// return attributes;
//}
- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Layout Attributes For Header: %# %ld %ld", elementKind, [indexPath row], [indexPath section]);
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
[attributes setFrame:CGRectMake(0, 0, contentWidth /*320*/, 75.0f)];
return attributes;
}
As you can see in MyFlowLayout, there are things I've tried but still it didn't call viewForSupplementaryElementOfKind. I tried implementing layoutAttributesForItemAtIndexPath since I have layoutAttributesForSupplementaryViewOfKind. I tried also using fixed numbers like the 75 and 320 that you see just to check if the header would be generated. The delegate that you see, it's just for getting a height of a view.
Since I've given the header enough space to be seen and left NSLogs all over and yet (UICollectionReusableView*)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath is not being called.
Here are some that I've looked and tried: stackoverflow but as you can see from the commented code that I've included. It still didn't work.
Thanks for the help.
I also had a problem with this and my solution was to simply add attributes for section in prepareLayout
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader withIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
attributes.frame = CGRectMake(0, 0, self.collectionView.frame.size.width, 100);
[cachedAttributes addObject:attributes];
Add the default size of header section:
collectionViewLayout.headerReferenceSize = CGSize(width, height)
The default size values are (0, 0). Thats why header is not displaying.
OR
There is also another way for it, implement the delegate method for UICollectionView:
collectionView(_:layout:referenceSizeForFooterInSection:)
I'm using a custom layout to get several background color sections using UICollectionReusableView's subclasses. This is the code:
- (void)prepareLayout
{
[super prepareLayout];
self.itemAttributes = [NSMutableArray new];
NSInteger numberOfSection = self.collectionView.numberOfSections;
for (int section = 0; section < numberOfSection; section++) {
if (section == self.decorationViewOfKinds.count)
break;
NSString *decorationViewOfKind = self.decorationViewOfKinds[section % self.decorationViewOfKinds.count];
if ([decorationViewOfKind isKindOfClass:[NSNull class]])
continue;
NSInteger lastIndex = [self.collectionView numberOfItemsInSection:section] - 1;
if (lastIndex < 0)
continue;
UICollectionViewLayoutAttributes *firstItem = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
UICollectionViewLayoutAttributes *lastItem = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow:lastIndex inSection:section]];
CGRect frame = CGRectUnion(firstItem.frame, lastItem.frame);
frame.origin.x -= self.sectionInset.top;
frame.size.height += self.sectionInset.bottom;
if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal) {
frame.size.width += self.sectionInset.left + self.sectionInset.right;
frame.size.height = self.collectionView.frame.size.height;
}
else {
frame.size.width = self.collectionView.frame.size.width;
frame.size.height += self.sectionInset.top + self.sectionInset.bottom;
}
UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:decorationViewOfKind withIndexPath:[NSIndexPath indexPathForRow:0 inSection:section]];
attributes.zIndex = -1;
attributes.frame = frame;
[self.itemAttributes addObject:attributes];
[self registerNib:[UINib nibWithNibName:decorationViewOfKind bundle:[NSBundle mainBundle]] forDecorationViewOfKind:decorationViewOfKind];
}
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *attributes = [NSMutableArray arrayWithArray:[super layoutAttributesForElementsInRect:rect]];
for (UICollectionViewLayoutAttributes *attribute in self.itemAttributes) {
if (!CGRectIntersectsRect(rect, attribute.frame))
continue;
[attributes addObject:attribute];
}
return attributes;
}
This code crashes sometimes on a device using iOS 8.4.1 throwing:
Fatal Exception: NSInternalInconsistencyException
no UICollectionViewLayoutAttributes instance for -layoutAttributesForDecorationViewOfKindOfKind: AlbumsSectionBackgroundDecoratorView at path {length = 2, path = 2 - 0}
It does not happen in the simulator, just in devices with iOS 8.4.1
Any ideas?
Thanks!
EDIT
The bug seems to be happening cause backpressure in the UICollectionView. I have avoided to reload the UICollectionView and seems to be working fine 💪🏼
How to Create multiple column in an one row.
Like this image!. https://pbs.twimg.com/media/CEuO0hUUUAARX_L.png !
You can also use gridview for your requirement like GMGridView or UIGridView
Check below sample code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* cellIdentifier = #"gridCell";
UITableViewCell *gridCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(gridCell == nil)
{
gridCell = [[[UITableViewCellalloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:cellIdentifier] autorelease];
gridCell.accessoryType = UITableViewCellAccessoryNone;
gridCell.selectionStyle = UITableViewCellSelectionStyleNone;
}
NSArray* items = [_grids objectAtIndex:indexPath.section];
int imageIndex = 0;
int yOffset = 0;
while (imageIndex < items.count)
{
int yPos = 4 + yOffset * 74;
for(int i = 0; i < 4; ++i)
{
CGRect rect = CGRectMake((18 + i * 80), yPos, 40, 40);
UIImageView* imageView = [self gridImageRect:rect forImage:[items objectAtIndex:imageIndex]];
[gridCell.contentView addSubview:imageView];
[imageView release];
rect = CGRectMake(((80 * i)-4), (yPos+44), 80, 12);
UILabel* label = [self descriptionOfImage:imageIndex inRect:rect];
[gridCell.contentView addSubview:label];
[label release];
++imageIndex;
}
++yOffset;
}
return gridCell;
}
I used UICollectionView and subClassing UICollectionViewLayout to get a circle scrolling view. Code in Custom Layout as below,
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
float minY = CGRectGetMinY(rect);
float maxY = CGRectGetMaxY(rect);
int startIndex = fmax(0.0 ,minY / 60);
int endIndex = fmin([self.collectionView numberOfItemsInSection:0]-1, maxY / 60);
NSMutableArray* array = [[NSMutableArray alloc]init];
for( int i = startIndex ;i<=endIndex ;i++)
{
NSIndexPath* path = [NSIndexPath indexPathForItem:i inSection:0];
UICollectionViewLayoutAttributes* attr = [self layoutAttributesForItemAtIndexPath:path];
[array addObject:attr];
}
return array;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
float peak = (self.collectionView.contentOffset.y+self.collectionView.frame.size.height/2.0)/60.0;
float x = 200 - fabs(indexPath.item - peak)*50;
UICollectionViewLayoutAttributes* attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attr.size = CGSizeMake(250, 50);
attr.center = CGPointMake(x, indexPath.item*55.0);
attr.hidden = NO;
return attr;
}
the initial state misses the 11th cell,but when I scroll, it will appear, why that wired.
i'm having problems to align the first row to the top when I have different UICollectionViewCell heights and I don't know why. It seems that minimumLineSpacingForSectionAtIndex method is not working.
Here is my result:
As you can see, the first row is not aligned to the top.
This is my code:
- (void)viewDidLoad
{
...
FlowLayout *flowLayout = [[FlowLayout alloc] init];
flowLayout.itemSize = CGSizeMake(152, 260);
flowLayout.sectionInset = UIEdgeInsetsMake( 5, 5, 5, 5);
flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical;
self.collectionView.collectionViewLayout = flowLayout;
...
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:
(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)
indexPath{
if (indexPath.row == 0)
return CGSizeMake(152, 200);
if (indexPath.row == 1)
return CGSizeMake(152, 270);
return CGSizeMake(152, 300);
}
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:
(UICollectionViewLayout*)collectionViewLayout
minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
return 5.0;
}
- (CGFloat)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout*)collectionViewLayout
minimumLineSpacingForSectionAtIndex:(NSInteger)section {
return 8.0;
}
This is the code of my FlowLayout:
#implementation FlowLayout
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSMutableArray *result = [NSMutableArray array];
NSInteger sectionCount = 1;
if ([self.collectionView.dataSource respondsToSelector:#selector(numberOfSectionsInCollectionView:)])
{
sectionCount = [self.collectionView.dataSource numberOfSectionsInCollectionView:self.collectionView];
}
for (int s = 0; s < sectionCount; s++)
{
NSInteger itemCount = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:s];
for (int i = 0; i < itemCount; i++)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:s];
UICollectionViewLayoutAttributes *layoutAttributes =
[self layoutAttributesForSupplementaryViewOfKind:UICollectionElementKindSectionHeader atIndexPath:indexPath];
if (layoutAttributes != nil) {
[result addObject:layoutAttributes];
}
UICollectionViewLayoutAttributes *layout = [self layoutAttributesForItemAtIndexPath:indexPath];
if (CGRectIntersectsRect(rect, layout.frame))
{
[result addObject:layout];
}
}
}
return result;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes* atts =
[super layoutAttributesForItemAtIndexPath:indexPath];
if (indexPath.item == 0 || indexPath.item == 1) // degenerate case 1, first item of section
return atts;
NSIndexPath* ipPrev =
[NSIndexPath indexPathForItem:indexPath.item-2 inSection:indexPath.section];
CGRect fPrev = [self layoutAttributesForItemAtIndexPath:ipPrev].frame;
CGFloat rightPrev = fPrev.origin.y + fPrev.size.height + 10;
if (atts.frame.origin.y <= rightPrev) // degenerate case 2, first item of line
return atts;
CGRect f = atts.frame;
f.origin.y = rightPrev;
atts.frame = f;
return atts;
}
- (BOOL) shouldInvalidateLayoutForBoundsChange:(CGRect)newBound {
return YES;
}
What you are experiencing is a normal cell placement when using the UICollectionViewFlowLayout.
You have to tweak the layout attributes being returned by the flow layout. To do so, override the layoutAttributesForElementsInRect: method and any of the methods that return layout attributes. Modify the attributes provided by the parent class, and then return them. The attribute you have to modify is frame.
A good example of doing it is a sample code from Apple - Custom Layouts: A Worked Example
Update after attaching implementation of the layout.
Looks like in the layoutAttributesForItemAtIndexPath: method you are not adjusting the frame for first item (index 0). You are returning the attributes you get from parent class. Change the frame's origin.y to 0 for item 0.