1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @protocol WaterLayoutDelegate <NSObject>
@required - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
@end @interface WJY_WaterFallLayout : UICollectionViewLayout @property (nonatomic, assign) id<WaterLayoutDelegate> delegate;
@property (nonatomic, assign) NSInteger lineCount;
@property (nonatomic, assign) CGFloat verticalSpacing;
@property (nonatomic, assign) CGFloat horizontalSpacing; @property (nonatomic, assign) UIEdgeInsets sectionInset; @end
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
| #import "WJY_WaterFallLayout.h"
@interface WJY_WaterFallLayout() @property (nonatomic, retain) NSMutableArray *heights; @property (nonatomic, retain) NSMutableArray *originX; @property (nonatomic, retain) NSMutableDictionary *itemsArrange;
@property (nonatomic, retain) NSMutableDictionary *itemsInitialArrange;
@end @implementation WJY_WaterFallLayout #pragma mark - 重写,应 始终调用子类 - (void)prepareLayout { NSInteger cellCount = [self.collectionView numberOfItemsInSection:0]; if (cellCount == 0) { return ; } self.delegate = (id<WaterLayoutDelegate>)self.collectionView.delegate; self.itemsArrange = [NSMutableDictionary dictionary]; self.itemsInitialArrange = [NSMutableDictionary dictionary]; [self initAllarrays];
for (NSInteger i = 0; i < cellCount; i++) { [ self layoutForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]]; }
} #pragma 初始化所以数组 - (void)initAllarrays { self.heights = [NSMutableArray array]; self.originX = [NSMutableArray array]; CGFloat itemWidth = ([UIScreen mainScreen].bounds.size.width - self.sectionInset.left - self.sectionInset.right - (self.lineCount - 1) * self.horizontalSpacing) / self.lineCount; for (NSInteger i = 0; i < self.lineCount; i++) { [self.heights addObject:[NSNumber numberWithDouble:self.sectionInset.top]]; CGFloat oringin_x = 0.0; if (i == 0) { oringin_x = self.sectionInset.left; } else { oringin_x = [self.originX[i - 1] doubleValue] + itemWidth + self.horizontalSpacing; } [self.originX addObject:[NSNumber numberWithDouble: oringin_x]]; }
} #pragma mark - itme设置 - (void)layoutForItemAtIndexPath:(NSIndexPath *)indexPath { CGRect rect = CGRectZero; CGSize size = [self.delegate collectionView:self.collectionView layout:self sizeForItemAtIndexPath:indexPath]; rect.size.height = size.height; rect.size.width = ([UIScreen mainScreen].bounds.size.width - self.sectionInset.left - self.sectionInset.right - (self.lineCount - 1) * self.horizontalSpacing) / self.lineCount; NSInteger index = [self getLowerHeightRowIndex:self.heights]; rect.origin.x = [self.originX[index] doubleValue]; rect.origin.y = [self.heights[index] doubleValue]; CGFloat newHeight = rect.origin.y + rect.size.height + self.verticalSpacing; [self.heights replaceObjectAtIndex:index withObject:[NSNumber numberWithDouble: newHeight]]; [self.itemsArrange setObject:indexPath forKey:NSStringFromCGRect(rect)]; [self.itemsInitialArrange setObject:indexPath forKey:NSStringFromCGRect(CGRectMake(rect.origin.x, rect.origin.y - [UIScreen mainScreen].bounds.size.height, rect.size.width, rect.size.height))]; } #pragma mark - 子类必须重写此方法并使用它来返回的宽度和高度的视图的内容。这些值表示的宽度和高度的所有内容,视图使用此信息来配置其自身内容的大小,以便滚动。 - (CGSize)collectionViewContentSize { CGFloat heightest = [self getHeightest:self.heights]; CGSize size = CGSizeMake(0, heightest); return size; } #pragma mark - 设置布局信息 - (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath { UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; NSArray *keyArr = self.itemsArrange.allKeys; for (NSString *rectStr in keyArr) {
if (self.itemsArrange[rectStr] != indexPath) { continue; } CGRect rect = CGRectFromString(rectStr); attributes.frame = rect; break; } return attributes; } #pragma mark - 重新自定义layout - (UICollectionViewLayoutAttributes *)initialLayoutAttributesForAppearingItemAtIndexPath:(NSIndexPath *)itemIndexPath { UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:itemIndexPath]; NSArray *keyArr = self.itemsArrange.allKeys; for (NSString *rectStr in keyArr) { if (self.itemsInitialArrange[rectStr] != itemIndexPath) { continue; } CGRect rect = CGRectFromString(rectStr); attributes.frame = rect; break; } return attributes; }
#pragma mark - 布局属性返回数组 视图在给定矩形 - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect { CGFloat up = rect.origin.y; CGFloat down = rect.origin.y + rect.size.height; NSMutableArray *attributes = [NSMutableArray array]; for (NSString *rectStr in self.itemsArrange) { CGRect itemRect = CGRectFromString(rectStr); if (itemRect.origin.y <= down && itemRect.origin.y + itemRect.size.height >= up) { NSIndexPath *indexPath = [self.itemsArrange objectForKey:rectStr]; [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]]; } } return attributes; } # pragma mark - 获取低行高 - (NSInteger)getLowerHeightRowIndex:(NSMutableArray *)height { if (height.count == 0) { return 0; } NSInteger index = 0; CGFloat heightest = [height[0] doubleValue]; for (NSInteger i = 1; i < height.count; i++) { index = heightest > [height[i] doubleValue] ? i : index; } return index; } # pragma mark - 获取高度 - (CGFloat)getHeightest:(NSMutableArray *)height { if (height.count == 0) { return 0; } CGFloat heightest = self.sectionInset.top; for (NSInteger i = 0; i < height.count; i++) { heightest = heightest > [height[i] doubleValue] ? heightest : [height[i] doubleValue]; } return heightest; }
@end
|