Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollection View Flow Layout Vertical Align

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 ?

enter image description here

like image 320
R.Lambert Avatar asked May 30 '13 13:05

R.Lambert


2 Answers

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     } } 
like image 162
Fabio Felici Avatar answered Sep 23 '22 20:09

Fabio Felici


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 
like image 34
DongXu Avatar answered Sep 24 '22 20:09

DongXu