diff --git a/doric-iOS/Pod/Classes/Shader/DoricFlowLayoutNode.m b/doric-iOS/Pod/Classes/Shader/DoricFlowLayoutNode.m index 20fcd00b..8aa60813 100644 --- a/doric-iOS/Pod/Classes/Shader/DoricFlowLayoutNode.m +++ b/doric-iOS/Pod/Classes/Shader/DoricFlowLayoutNode.m @@ -17,6 +17,7 @@ // Created by pengfei.zhou on 2019/11/28. // +#import #import "DoricFlowLayoutNode.h" #import "DoricFlowLayoutItemNode.h" #import "DoricExtensions.h" @@ -44,6 +45,9 @@ @interface DoricFlowLayout : UICollectionViewLayout @property(nonatomic, readonly) CGFloat rowSpace; @property(nonatomic, strong) NSMutableDictionary *columnHeightInfo; @property(nonatomic, weak) id delegate; +@property(nonatomic, copy) NSArray *layoutAttributes; +@property(nonatomic, copy) NSArray *unionRects; +@property(nonatomic, strong) NSArray *swapDisabled; @end @implementation DoricFlowLayout @@ -75,63 +79,104 @@ - (void)prepareLayout { for (int i = 0; i < self.columnCount; i++) { self.columnHeightInfo[@(i)] = @(0); } -} - -- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { - for (int i = 0; i < self.columnCount; i++) { - self.columnHeightInfo[@(i)] = @(0); - } NSMutableArray *array = [NSMutableArray array]; NSInteger count = [self.collectionView numberOfItemsInSection:0]; - for (int i = 0; i < count; i++) { - UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]; - [array addObject:attrs]; - } - return array; -} - -- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { + NSNumber *minYOfColumn = @(0); NSArray *keys = self.columnHeightInfo.allKeys; NSArray *sortedKeys = [keys sortedArrayUsingComparator:^NSComparisonResult(NSNumber *obj1, NSNumber *obj2) { return ([obj1 intValue] <= [obj2 intValue] ? NSOrderedAscending : NSOrderedDescending); }]; - - for (NSNumber *key in sortedKeys) { - if ([self.columnHeightInfo[key] floatValue] < [self.columnHeightInfo[minYOfColumn] floatValue]) { - minYOfColumn = key; - } - } - CGFloat width = [self.delegate doricFlowLayoutItemWidthAtIndexPath:indexPath]; - CGFloat height = [self.delegate doricFlowLayoutItemHeightAtIndexPath:indexPath]; - CGFloat x = 0; - CGFloat y = [self.columnHeightInfo[minYOfColumn] floatValue]; - if (y > 0) { - y += self.rowSpace; - } - - if ([self.delegate doricFlowLayoutItemFullSpan:indexPath]) { - NSNumber *maxYColumn = @(0); + + for (int i = 0; i < count; i++) { + minYOfColumn = @(0); + NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0] ; + + UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; + for (NSNumber *key in sortedKeys) { - if ([self.columnHeightInfo[key] floatValue] > [self.columnHeightInfo[maxYColumn] floatValue]) { - maxYColumn = key; + if ([self.columnHeightInfo[key] floatValue] < [self.columnHeightInfo[minYOfColumn] floatValue]) { + minYOfColumn = key; } } - CGFloat maxY = [self.columnHeightInfo[maxYColumn] floatValue]; - y = maxY + self.rowSpace; - for (NSNumber *key in self.columnHeightInfo.allKeys) { - self.columnHeightInfo[key] = @(y + height); + + CGFloat width = [self.delegate doricFlowLayoutItemWidthAtIndexPath:indexPath]; + CGFloat height = [self.delegate doricFlowLayoutItemHeightAtIndexPath:indexPath]; + CGFloat x = 0; + CGFloat y = [self.columnHeightInfo[minYOfColumn] floatValue]; + if (y > 0) { + y += self.rowSpace; } - } else { - CGFloat columnWidth = (self.collectionView.width - (self.columnCount - 1) * self.columnSpace) / self.columnCount; - x = (columnWidth + self.columnSpace) * [minYOfColumn integerValue]; - self.columnHeightInfo[minYOfColumn] = @(y + height); + + if ([self.delegate doricFlowLayoutItemFullSpan:indexPath]) { + NSNumber *maxYColumn = @(0); + for (NSNumber *key in sortedKeys) { + if ([self.columnHeightInfo[key] floatValue] > [self.columnHeightInfo[maxYColumn] floatValue]) { + maxYColumn = key; + } + } + CGFloat maxY = [self.columnHeightInfo[maxYColumn] floatValue]; + y = maxY + self.rowSpace; + for (NSNumber *key in self.columnHeightInfo.allKeys) { + self.columnHeightInfo[key] = @(y + height); + } + } else { + CGFloat columnWidth = (self.collectionView.width - (self.columnCount - 1) * self.columnSpace) / self.columnCount; + x = (columnWidth + self.columnSpace) * [minYOfColumn integerValue]; + self.columnHeightInfo[minYOfColumn] = @(y + height); + } + attrs.frame = CGRectMake(x, y, width, height); + + [array addObject:attrs]; } - UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; - attrs.frame = CGRectMake(x, y, width, height); + self.layoutAttributes = array; + + NSMutableArray *mutableCopy = [NSMutableArray array]; + long idx = 0; + NSInteger itemCounts = count; + while(idx < itemCounts){ + CGRect rect1 = self.layoutAttributes[idx].frame; + idx = MIN(idx + count, itemCounts) - 1; + CGRect rect2 = self.layoutAttributes[idx].frame; + [mutableCopy addObject:[NSValue valueWithCGRect:CGRectUnion(rect1, rect2)]]; + idx += 1; + } + self.unionRects = mutableCopy; +} + +- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { + NSInteger begin = 0; + NSInteger end = self.unionRects.count; + NSMutableArray *attrs = [NSMutableArray array]; + + for (int i = 0; i < end; i++) { + if (CGRectIntersectsRect(rect, [self.unionRects[i] CGRectValue])) { + begin = i * self.layoutAttributes.count; + break; + } + } + + for (long i = self.unionRects.count - 1; i >= 0; i--) { + if (CGRectIntersectsRect(rect, [self.unionRects[i] CGRectValue])) { + end = MIN((i + 1) * self.layoutAttributes.count, self.layoutAttributes.count); + break; + } + } + + for (NSInteger i = begin; i < end; i++) { + UICollectionViewLayoutAttributes *attr = self.layoutAttributes[i]; + if (CGRectIntersectsRect(rect, attr.frame)) { + [attrs addObject:attr]; + } + } + return attrs; } +- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { + return self.layoutAttributes[indexPath.row]; +} + - (CGSize)collectionViewContentSize { CGFloat width = self.collectionView.width; CGFloat height = 0; @@ -175,11 +220,12 @@ @interface DoricFlowLayoutNode ()