blob: e6be7c4ecdb22eb0711c822c45d63bf4fa08bead [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/home_customization/ui/centered_flow_layout.h"
@implementation CenteredFlowLayout
- (NSArray<UICollectionViewLayoutAttributes*>*)
layoutAttributesForElementsInRect:(CGRect)rect {
NSArray<UICollectionViewLayoutAttributes*>* originalAttributes =
[super layoutAttributesForElementsInRect:rect];
NSMutableArray<UICollectionViewLayoutAttributes*>* updatedAttributes =
[[NSMutableArray alloc] init];
CGFloat contentWidth = self.collectionView.bounds.size.width -
self.sectionInset.left - self.sectionInset.right;
NSMutableDictionary<
NSNumber*, NSMutableArray<UICollectionViewLayoutAttributes*>*>* rows =
[NSMutableDictionary dictionary];
// Group attributes by row based on Y position (the vertical center of the
// row).
for (UICollectionViewLayoutAttributes* attributes in originalAttributes) {
if (attributes.representedElementCategory ==
UICollectionElementCategoryCell) {
CGFloat centerY = CGRectGetMidY(attributes.frame);
NSNumber* rowKey = @(centerY);
if (!rows[rowKey]) {
rows[rowKey] = [NSMutableArray array];
}
[rows[rowKey] addObject:[attributes copy]];
} else {
[updatedAttributes
addObject:[attributes copy]]; // Headers, footers, etc.
}
}
// Adjust frames for each row.
for (NSNumber* key in rows) {
NSMutableArray<UICollectionViewLayoutAttributes*>* rowAttributes =
rows[key];
if (rowAttributes.count == 0) {
continue;
}
CGFloat interitemSpacing = self.minimumInteritemSpacing;
// Calculate the total width of the row by finding the min and max X
// coordinates of the items.
CGFloat minX = CGFLOAT_MAX;
CGFloat maxX = CGFLOAT_MIN;
for (UICollectionViewLayoutAttributes* attr in rowAttributes) {
minX = MIN(minX, CGRectGetMinX(attr.frame));
maxX = MAX(maxX, CGRectGetMaxX(attr.frame));
}
CGFloat totalRowWidth = maxX - minX;
// If the whole width is not taken, the custom sorting logic is used (i.e.,
// simply add an offset to the X coord).
if (totalRowWidth < contentWidth) {
CGFloat offset = (contentWidth - totalRowWidth) / 2.0;
CGFloat currentX = self.sectionInset.left + offset;
// Sort attributes by their original X position to maintain order.
[rowAttributes sortUsingComparator:^NSComparisonResult(
UICollectionViewLayoutAttributes* obj1,
UICollectionViewLayoutAttributes* obj2) {
return [@(obj1.frame.origin.x) compare:@(obj2.frame.origin.x)];
}];
for (UICollectionViewLayoutAttributes* attr in rowAttributes) {
CGRect frame = attr.frame;
frame.origin.x = currentX;
attr.frame = frame;
currentX += frame.size.width + interitemSpacing;
}
}
[updatedAttributes addObjectsFromArray:rowAttributes];
}
return updatedAttributes;
}
@end