当前位置:网站首页>Waterfall flow (custom layout implementation)
Waterfall flow (custom layout implementation)
2022-07-30 07:35:00 【rhubarb_yellow】
This article mainly shares how to implement waterfall flow with custom layout,For other implementations of waterfall flow, please refer to my other article 瀑布流(UIScrollView实现),利用UICollectionViewA very big advantage of implementing waterfall flow is that we don't have to care about the reuse mechanism,Just focus on how to customize the layout to arrange each onecell的位置
新建一个布局DSWaterFlowLayout,继承自UICollectionViewLayout
一、Provides available interfaces(列数,行间距,列间距,边距)
在.h文件中:
/** * The spacing of each line */
@property (nonatomic, assign) CGFloat rowMargin;
/** * The spacing of each column */
@property (nonatomic, assign) CGFloat columnMargin;
/** * 周围的edgeInset */
@property (nonatomic, assign) UIEdgeInsets sectionEdgeInset;
/** * 列数 */
@property (nonatomic, assign) NSInteger columnsCount;在.m文件中的initThe method initializes the default value:
- (instancetype)init
{
if (self = [super init]) {
self.rowMargin = 10;
self.columnMargin = 10;
self.columnsCount = 3;
self.sectionEdgeInset = UIEdgeInsetsMake(10, 10, 10, 10);
}
return self;
}二、 重写layoutAttributesForItemAtIndexPath方法和shouldInvalidateLayoutForBoundsChange方法,The purpose of this method is to arrange each onecell的位置,然后把cell的UICollectionViewLayoutAttributes属性返回出去
- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
return YES;
}1> 实现思路就是:Determine the maximum value of each columnY值,找出YThe column with the smallest value,然后添加cellto this column,So we can create a dictionary to hold the max of each columnY值,key就是列数,value就是最大Y值
/** * Used to load maxY值的字典 */
@property (nonatomic, strong) NSMutableDictionary *maxYDict;- (NSMutableDictionary *)maxYDict
{
if (_maxYDict== nil) {
self.maxYDict = [[NSMutableDictionary alloc] init];
for (int i = 0; i < self.columnsCount; i++) {
NSString *column = [NSString stringWithFormat:@"%d", i];
self.maxYDict[column] = @(self.sectionEdgeInset.top);
}
}
return _maxYDict;
}2> 遍历字典,找出YThe column with the smallest value,然后设置width,X,Y值,Also remember to keep up to dateY值,至于heightThe true aspect ratio of the image is required,So we need to get the model,But in order to reduce coupling and usability,So proxy can be used
在.h文件中:
@protocol DSWaterFlowLayoutDelegate <NSObject>
@required
/** * According to the actual aspect ratio and width of the image,Calculate the actual height */
- (CGFloat)waterFlowLayout:(DSWaterFlowLayout *)waterFlowLayout heightForWidth:(CGFloat)width atIndexPath:(NSIndexPath *)indexPath;
@end@property (nonatomic,weak) id<DSWaterFlowLayoutDelegate> delegate;在.m文件中:
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"0-----");
// By default the smallest column is th0列
__block NSString *minColumn = @"0";
// 遍历字典,找出YThe column with the smallest value
[self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString * column, NSNumber *maxY, BOOL * _Nonnull stop) {
if ([self.maxYDict[column] integerValue] < [self.maxYDict[minColumn] integerValue]) {
minColumn = column;
}
}];
// 计算尺寸
CGFloat width = (self.collectionView.frame.size.width - self.sectionEdgeInset.left - self.sectionEdgeInset.right - (self.columnsCount - 1) * self.columnMargin) / self.columnsCount;
CGFloat height = [self.delegate waterFlowLayout:self heightForWidth:width atIndexPath:indexPath];
// 计算位置
CGFloat x = self.sectionEdgeInset.right + (width + self.columnMargin) * [minColumn integerValue];
CGFloat y = [self.maxYDict[minColumn] integerValue] + self.rowMargin;
// 更新Y值
self.maxYDict[minColumn] = @(y + height);
// 取得indexPath位置上cell的UICollectionViewLayoutAttributes
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
attrs.frame = CGRectMake(x, y, width, height);
return attrs;
}三、告诉collectionView的滚动范围
- (CGSize)collectionViewContentSize
{
// By default the smallest column is th0列
__block NSString *maxColumn = @"0";
// 遍历字典,找出YThe column with the smallest value
[self.maxYDict enumerateKeysAndObjectsUsingBlock:^(NSString * column, NSNumber *maxY, BOOL * _Nonnull stop) {
if ([self.maxYDict[column] integerValue] > [self.maxYDict[maxColumn] integerValue]) {
maxColumn = column;
}
}];
return CGSizeMake(0, [self.maxYDict[maxColumn] integerValue] + self.sectionEdgeInset.bottom);
}In fact, the layout is now complete,But the program still has some problems.首先,在滚动的时候collectionView里面的所有cellwill be recalculated,Hence the largest in the dictionaryY值会越来越大,So the dictionary should be emptied when rearranging.
在滚动的时候,The system will call it onceprepareLayout方法,两次layoutAttributesForElementsInRect方法,所以我们应该在prepareLayoutmethod to clear the dictionary,And save all the calculated onesUICollectionViewLayoutAttributes属性,So create an array to hold itUICollectionViewLayoutAttributes属性,并且只在prepareLayoutCalculate in method,只需要在layoutAttributesForElementsInRectIt is enough to return the calculated property in the method.
/** * Holds all layout properties */
@property (nonatomic, strong) NSMutableArray *attrsArray;- (NSMutableArray *)attrsArray
{
if (_attrsArray== nil) {
self.attrsArray = [[NSMutableArray alloc] init];
}
return _attrsArray;
}- (void)prepareLayout
{
[super prepareLayout];
// 清空Y值
for (int i = 0; i < self.columnsCount; i++) {
NSString *column = [NSString stringWithFormat:@"%d", i];
self.maxYDict[column] = @(self.sectionEdgeInset.top);
}
NSInteger count = [self.collectionView numberOfItemsInSection:0];
// Clear the previous properties
[self.attrsArray removeAllObjects];
for (int i = 0; i < count; i++) {
UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:0]];
[self.attrsArray addObject:attrs];
}
}- (NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{
return self.attrsArray;
}至此,整个布局就完成了,是不是感觉比UIScrollViewIt is much simpler to implement!
边栏推荐
- vscode set sublime theme
- QT serial port dynamically displays a large number of data waveform curves in real time (5) ======== "Final perfect solution version"
- STM32F103连接L9110S电机驱动控制小水泵
- VsCode与Sublime编辑器优缺点对比
- 原力计划微服务实战|集中配置中心Config非对称加密与安全管理
- Biotin-NH2|CAS:111790-37-5(生物素-氨基)是一种生物素化化合物
- 陕西Biotin-LC_CAS:72040-64-3_N-生物素氨基己酸供应商价格
- 图扑数字孪生青岛城轨,赋能智慧交通低碳发展
- Biotinyl Cystamine_CAS:128915-82-2_生物素半胱胺
- ES6 syntax notes (ES6~ES11)
猜你喜欢
随机推荐
------实现二叉搜索树BST
The most complete difference between sizeof and strlen, as well as pointer and array operation analysis
关于memcache内核,全网最通俗的讲解
用于标记蛋白质和抗体的Biotin-LC-Sulfo-NHS|CAS:191671-46-2
不依赖框架的文件下载
c语言编程练习
网络协议04 - 物理层和数据链路层
基于精灵(Sprite)管道烟雾流动效果
测试第一题
一种分布式深度学习编程新范式:Global Tensor
Biotinyl Cystamine_CAS:128915-82-2_生物素半胱胺
数码管动态显示及模块化编程
QT serial port dynamically displays a large number of data waveform curves in real time (5) ======== "Final perfect solution version"
网络协议01 - 基础概念
元宇宙与图扑国风的碰撞,科技与文化的虚实融合
ParseException line 8:13 mismatched input ‘(‘ expecting ) near ‘int‘ in create table statement
单片机之流水灯
How to open terminal in VsCode
Biotin-PEG4-DADPS-Picolyl-azide(CAS:2599839-59-3)生物素试剂
Delete all files containing a keyword in the current path









