Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I studied more of how <code>UICollectionViewLayout</code>s work and figured out how to solve it. I have an <code>UICollectionReusableView</code> subclass called <code>OrangeView</code> that will be positioned between my views, than I wrote an <code>UICollectionViewFlowLayout</code> subclass called <code>CategoriesLayout</code> that will deal with my layout.</p> <p>Sorry for the big block of code, but here is how it looks like:</p> <pre><code>@implementation CategoriesLayout - (void)prepareLayout { // Registers my decoration views. [self registerClass:[OrangeView class] forDecorationViewOfKind:@"Vertical"]; [self registerClass:[OrangeView class] forDecorationViewOfKind:@"Horizontal"]; } - (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind atIndexPath:(NSIndexPath *)indexPath { // Prepare some variables. NSIndexPath *nextIndexPath = [NSIndexPath indexPathForItem:indexPath.row+1 inSection:indexPath.section]; UICollectionViewLayoutAttributes *cellAttributes = [self layoutAttributesForItemAtIndexPath:indexPath]; UICollectionViewLayoutAttributes *nextCellAttributes = [self layoutAttributesForItemAtIndexPath:nextIndexPath]; UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:decorationViewKind withIndexPath:indexPath]; CGRect baseFrame = cellAttributes.frame; CGRect nextFrame = nextCellAttributes.frame; CGFloat strokeWidth = 4; CGFloat spaceToNextItem = 0; if (nextFrame.origin.y == baseFrame.origin.y) spaceToNextItem = (nextFrame.origin.x - baseFrame.origin.x - baseFrame.size.width); if ([decorationViewKind isEqualToString:@"Vertical"]) { CGFloat padding = 10; // Positions the vertical line for this item. CGFloat x = baseFrame.origin.x + baseFrame.size.width + (spaceToNextItem - strokeWidth)/2; layoutAttributes.frame = CGRectMake(x, baseFrame.origin.y + padding, strokeWidth, baseFrame.size.height - padding*2); } else { // Positions the horizontal line for this item. layoutAttributes.frame = CGRectMake(baseFrame.origin.x, baseFrame.origin.y + baseFrame.size.height, baseFrame.size.width + spaceToNextItem, strokeWidth); } layoutAttributes.zIndex = -1; return layoutAttributes; } - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { NSArray *baseLayoutAttributes = [super layoutAttributesForElementsInRect:rect]; NSMutableArray * layoutAttributes = [baseLayoutAttributes mutableCopy]; for (UICollectionViewLayoutAttributes *thisLayoutItem in baseLayoutAttributes) { if (thisLayoutItem.representedElementCategory == UICollectionElementCategoryCell) { // Adds vertical lines when the item isn't the last in a section or in line. if (!([self indexPathLastInSection:thisLayoutItem.indexPath] || [self indexPathLastInLine:thisLayoutItem.indexPath])) { UICollectionViewLayoutAttributes *newLayoutItem = [self layoutAttributesForDecorationViewOfKind:@"Vertical" atIndexPath:thisLayoutItem.indexPath]; [layoutAttributes addObject:newLayoutItem]; } // Adds horizontal lines when the item isn't in the last line. if (![self indexPathInLastLine:thisLayoutItem.indexPath]) { UICollectionViewLayoutAttributes *newHorizontalLayoutItem = [self layoutAttributesForDecorationViewOfKind:@"Horizontal" atIndexPath:thisLayoutItem.indexPath]; [layoutAttributes addObject:newHorizontalLayoutItem]; } } } return layoutAttributes; } @end </code></pre> <p>I also wrote a category with some methods to check if an index path is the last in a line, in the last line or the last in a section:</p> <pre><code>@implementation UICollectionViewFlowLayout (Helpers) - (BOOL)indexPathLastInSection:(NSIndexPath *)indexPath { NSInteger lastItem = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:indexPath.section] -1; return lastItem == indexPath.row; } - (BOOL)indexPathInLastLine:(NSIndexPath *)indexPath { NSInteger lastItemRow = [self.collectionView.dataSource collectionView:self.collectionView numberOfItemsInSection:indexPath.section] -1; NSIndexPath *lastItem = [NSIndexPath indexPathForItem:lastItemRow inSection:indexPath.section]; UICollectionViewLayoutAttributes *lastItemAttributes = [self layoutAttributesForItemAtIndexPath:lastItem]; UICollectionViewLayoutAttributes *thisItemAttributes = [self layoutAttributesForItemAtIndexPath:indexPath]; return lastItemAttributes.frame.origin.y == thisItemAttributes.frame.origin.y; } - (BOOL)indexPathLastInLine:(NSIndexPath *)indexPath { NSIndexPath *nextIndexPath = [NSIndexPath indexPathForItem:indexPath.row+1 inSection:indexPath.section]; UICollectionViewLayoutAttributes *cellAttributes = [self layoutAttributesForItemAtIndexPath:indexPath]; UICollectionViewLayoutAttributes *nextCellAttributes = [self layoutAttributesForItemAtIndexPath:nextIndexPath]; return !(cellAttributes.frame.origin.y == nextCellAttributes.frame.origin.y); } @end </code></pre> <p>And this is the final result:</p> <p><img src="https://i.stack.imgur.com/j1m0V.png" alt="Final Result"></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload