By default, when you are using the flow layout in a collection view, cells are centered vertically. Is there a way to change this alignment ?
Swift 4 with functional oriented approach:
class TopAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout { override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { let attributes = super.layoutAttributesForElements(in: rect)? .map { $0.copy() } as? [UICollectionViewLayoutAttributes] attributes? .reduce([CGFloat: (CGFloat, [UICollectionViewLayoutAttributes])]()) { guard $1.representedElementCategory == .cell else { return $0 } return $0.merging([ceil($1.center.y): ($1.frame.origin.y, [$1])]) { ($0.0 < $1.0 ? $0.0 : $1.0, $0.1 + $1.1) } } .values.forEach { minY, line in line.forEach { $0.frame = $0.frame.offsetBy( dx: 0, dy: minY - $0.frame.origin.y ) } } return attributes } }
following code worked for me
@interface TopAlignedCollectionViewFlowLayout : UICollectionViewFlowLayout - (void)alignToTopForSameLineElements:(NSArray *)sameLineElements; @end @implementation TopAlignedCollectionViewFlowLayout - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect; { NSArray *attrs = [super layoutAttributesForElementsInRect:rect]; CGFloat baseline = -2; NSMutableArray *sameLineElements = [NSMutableArray array]; for (UICollectionViewLayoutAttributes *element in attrs) { if (element.representedElementCategory == UICollectionElementCategoryCell) { CGRect frame = element.frame; CGFloat centerY = CGRectGetMidY(frame); if (ABS(centerY - baseline) > 1) { baseline = centerY; [self alignToTopForSameLineElements:sameLineElements]; [sameLineElements removeAllObjects]; } [sameLineElements addObject:element]; } } [self alignToTopForSameLineElements:sameLineElements];//align one more time for the last line return attrs; } - (void)alignToTopForSameLineElements:(NSArray *)sameLineElements { if (sameLineElements.count == 0) { return; } NSArray *sorted = [sameLineElements sortedArrayUsingComparator:^NSComparisonResult(UICollectionViewLayoutAttributes *obj1, UICollectionViewLayoutAttributes *obj2) { CGFloat height1 = obj1.frame.size.height; CGFloat height2 = obj2.frame.size.height; CGFloat delta = height1 - height2; return delta == 0. ? NSOrderedSame : ABS(delta)/delta; }]; UICollectionViewLayoutAttributes *tallest = [sorted lastObject]; [sameLineElements enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes *obj, NSUInteger idx, BOOL *stop) { obj.frame = CGRectOffset(obj.frame, 0, tallest.frame.origin.y - obj.frame.origin.y); }]; } @end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With