Configure UICollectionViewFlowLayout to layout rows from bottom to top
The very helpful answer by @insane-36 showed a way to do it when collectionView.bounds == collectionView.collectionViewContentSize
.
But if you wish to support the case where collectionView.bounds < collectionViewcontentSize
, then I believe you need to re-map the rects exactly to support scrolling properly. If you wish to support the case where collectionView.bounds > collectionViewContentSize
, then you need to override collectionViewContentSize
to ensure the content rect is positioned at the bottom of the collectionView (since otherwise it will be positioned at the top, due to the top-to-bottom default behavior of UIScrollView
).
So the full solution is a bit more involved, and I ended up developing it here: https://github.com/algal/ALGReversedFlowLayout.
You could basically implement it with a simple logic, however this seems to be some how odd. If the collectionview contentsize is same as that of the collectionview bounds or if all the cells are visible then you could implement this with simple flowLayout as this,
@implementation SimpleFlowLayout
- (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{
CGSize contentSize = self.collectionViewContentSize;
CGRect frame = attribute.frame;
frame.origin.x = contentSize.width - attribute.frame.origin.x - attribute.frame.size.width;
frame.origin.y = contentSize.height - attribute.frame.origin.y - attribute.frame.size.height;
attribute.frame = frame;
}
@end
And so the figure looks like this,
But, if you use more rows, more than the that can be seen on the screen at the same time, then there seems to be some problem with reusing. Since the UICollectionView datasource method, collectionView:cellForItemAtIndexPath: works linearly and asks for the indexPath as the user scrolls, the cell are asked in the usual increasing indexPath pattern such as 1 --- 100 though we would want it to reverse this pattern. While scrolling we would need the collectionView to ask us for the items in decreasing order since our 100 item resides at top and 1 item at bottom. So, I dont have any particular idea about how this could be accomplished.