So basically my problem is that my uicollectionview's cells are ordered from top to bottom, rather than from left to right.
This is what it looks like -
[1][4][7]
[2][5][8]
[3][6][9]
This is what i want -
[1][2][3]
[4][5][6]
[7][8][9]
Another problem is when i scroll horizontally instead of moving the page a full 320points. It only moves enough to fit the next cell in the view.
this is what it looks like -
[2][3][10]
[5][6][ ]
[8][9][ ]
this is what i want -
[10][ ][ ]
[ ][ ][ ]
[ ][ ][ ]
I was hoping rendering it horizontally would fix it though. I'm still new to ios so please show me how to do it, all the tuts i searched are not for my exact problem or is outdated.
This is my solution, hope it helpful:
CELLS_PER_ROW = 4;
CELLS_PER_COLUMN = 5;
CELLS_PER_PAGE = CELLS_PER_ROW * CELLS_PER_COLUMN;
UICollectionViewFlowLayout* flowLayout = (UICollectionViewFlowLayout*)collectionView.collectionViewLayout;
flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
flowLayout.itemSize = new CGSize (size.width / CELLS_PER_ROW - delta, size.height / CELLS_PER_COLUMN - delta);
flowLayout.minimumInteritemSpacing = ..;
flowLayout.minimumLineSpacing = ..;
..
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger index = indexPath.row;
NSInteger page = index / CELLS_PER_PAGE;
NSInteger indexInPage = index - page * CELLS_PER_PAGE;
NSInteger row = indexInPage % CELLS_PER_COLUMN;
NSInteger column = indexInPage / CELLS_PER_COLUMN;
NSInteger dataIndex = row * CELLS_PER_ROW + column + page * CELLS_PER_PAGE;
id cellData = _data[dataIndex];
...
}
1) If you are using horizontal scrolling in collection view, the order will be like what you have
[1][4][7]
[2][5][8]
[3][6][9]
If you want this order to change, you have to use vertical scrolling.
2) If you want collection view to scroll a full page, enable paging from IB or
colloctionView.pagingEnabled = YES;
You have to implement a CustomLayout to solve this problem. Here is my solution:
/*
This is what it looks like -
[1][3] [5][7]
[2][4] [6][8]
This is what i want -
[1][2] [5][6]
[3][4] [7][8]
*/
#import "AWCustomFlowLayout.h"
CGFloat const kCellWidth = 130.0;
CGFloat const kCellHeight = 170.0;
CGFloat const kCellLineSpacing = 20.0;
CGFloat const kCellInteritemSpacing = 10.0;
@implementation AWCustomFlowLayout
- (instancetype)init {
self = [super init];
if (self) {
self.minimumLineSpacing = kCellLineSpacing;
self.minimumInteritemSpacing = kCellInteritemSpacing;
self.itemSize = CGSizeMake(kCellWidth, kCellHeight);
self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
self.sectionInset = UIEdgeInsetsMake(0, kCellLineSpacing, 0, 0);
}
return self;
}
- (UICollectionViewLayoutAttributes*)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewLayoutAttributes *attribute = [super layoutAttributesForItemAtIndexPath:indexPath];
[self modifyLayoutAttribute:attribute];
return attribute;
}
- (NSArray*)layoutAttributesForElementsInRect:(CGRect)rect{
NSArray *attributes = [super layoutAttributesForElementsInRect:rect];
for(UICollectionViewLayoutAttributes *attribute in attributes){
[self modifyLayoutAttribute:attribute];
}
return attributes;
}
- (void)modifyLayoutAttribute:(UICollectionViewLayoutAttributes*)attribute{
CGRect frame = attribute.frame;
NSInteger cellX = attribute.frame.origin.x;
NSInteger cellY = attribute.frame.origin.y;
NSInteger cellWidth = attribute.frame.size.width;
NSInteger const firstColumnX = kCellLineSpacing;
NSInteger const secondColumnX = kCellWidth + kCellLineSpacing*2;
NSInteger const firstRowY = 0;
NSInteger const secondRowY = kCellHeight + kCellInteritemSpacing;
BOOL isFirstColumn = cellX % firstColumnX == 0;
BOOL isSecondColumn = (cellX+cellWidth) % (secondColumnX+cellWidth) == 0;
BOOL isFirstRow = cellY == firstRowY;
BOOL isSecondRow = cellY == secondRowY;
if (isFirstColumn && isSecondRow) {
frame.origin.x += secondColumnX-firstColumnX;
frame.origin.y = firstRowY;
}
else if (isSecondColumn && isFirstRow) {
frame.origin.x -= secondColumnX-firstColumnX;
frame.origin.y = secondRowY;
}
attribute.frame = frame;
}
@end
Assuming that you are using a section for each "page", have a look at this picture, which describes how the cells are build:
so instead of [0..11] we want this order:
[0,3,6,9,1,4,7,10,2,5,8,11].
If you look further at the second array, you can rebuild this one using the number of columns and number of rows of your pages:
let columns: Int = 4
let rows: Int = 3
var correctRowOrder = [Int]()
for index in 0..<columns {
let array = Array(0..<rows).map {$0*columns}.map {$0+index}
correctRowOrder += array
}
// You can use this one within the cellForItemAt method provided by the collectionview!
let correctIndexPath = correctRowOrder[indexPath.row]
Remember to use sections for this solution!