UICollectionView - order cells horizontally

只谈情不闲聊 提交于 2019-12-01 07:33:19

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!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!