蘑菇街利用UIScrollView(基本和tableView一样实现重用) 实现思想为第一次或刷新时计算frame,同时用一个数组存放frame**计算思路。**用一个c语言数组存放每一列图片的最大Y值每一个cell计算Y值时都算出哪一列的y值最小,计算出来并把此frame设置为对应列的最大y值全部算完计算contentsizeUIScrollView比较特殊,layoutsubviews在每次滚动时都会调用,所以利用这点可以在layoutsubviews里让cell显示出来首先需要一个字典(dispalayCells)存放当前显示在屏幕上的cell还需要一个集合(reusableSet)存放创建过得的cell(即充当缓存池作用)遍历frame数组计算每个frame是否显示在屏幕上当CGRectGetMaxY(frame)>self.contentOffset.y&&CGRectGetMinY(frame)<self.contentOffset.y+self.frame.size.height时即显示在屏幕上,在判断dispalayCells中有没有此cell,如果为nil则调用数据源方法创建(数据源会像充当缓存池的集合中找,找不到符合条件的才会创建),加到scrollview上,并加入到dispalayCells中,并设置frame如果没显示在屏幕上,也判断之前是否显示在屏幕上,即dispalayCells中有没有此cell,如果为真,则把它从scrollview中删除,并从dispalayCells中删除,并加入到reusableSet中,每次刷新都需要把存放frame的数组和dispalayCells 和reusableSet清空,还有把所有cell移除,因为有可能cell全部变了,所以必须移除,时间处理即判断当前显示的cell的frame是否包含触摸点,谁包含即谁点击
代码如下
-(void)reloadData{ //没吃重新刷新都清除所有数据 [self.displayCells.allValues makeObjectsPerformSelector:@selector(removeFromSuperview)]; [self.displayCells removeAllObjects]; [self.cellFrames removeAllObjects]; [self.reusableCells removeAllObjects]; //总个数 NSInteger numbersOfCell=[self.dataSource numbersOfCellsInWaterFlowView:self]; //总列数 NSInteger numbersOfColumn=[self numbersOfColumn]; CGFloat marginLeft=[self marginWithType:LSWaterFlowViewMarginTypeLeft]; CGFloat marginTop=[self marginWithType:LSWaterFlowViewMarginTypeTop]; CGFloat marginRow=[self marginWithType:LSWaterFlowViewMarginTypeRow]; CGFloat marginCol=[self marginWithType:LSWaterFlowViewMarginTypeColumn]; CGFloat cellW=[self cellWidth]; //定义一个c语言的存放每一列的最大Y值 CGFloat columnMaxY[numbersOfColumn]; //开始全部设置为0.0 for (int i=0; i<numbersOfColumn; i++) { columnMaxY[i]=0.0; } for (int i=0; i<numbersOfCell; i++) { //假设第一列为最小Y NSInteger column=0; // 列号为0 CGFloat maxColumnY=columnMaxY[column]; for (int j=1; j<numbersOfColumn; j++) { if (maxColumnY>columnMaxY[j]) { maxColumnY=columnMaxY[j]; column=j; } } CGFloat cellY; CGFloat cellX=marginLeft+(cellW+marginCol)*column; CGFloat cellH=[self cellHeightAtIndex:i]; //第一次为0,所以得加上顶部边距 if (maxColumnY==0.0) { cellY=marginTop; }else{ cellY=maxColumnY+marginRow; } CGRect frame=CGRectMake(cellX, cellY, cellW, cellH); columnMaxY[column]=CGRectGetMaxY(frame); [self.cellFrames addObject:[NSValue valueWithCGRect:frame]]; } //计算contentSize CGFloat contentH=columnMaxY[0]; for (int i=1; i<numbersOfColumn; i++) { if (contentH<columnMaxY[i]) { contentH=columnMaxY[i]; } } CGFloat marginBottom=[self marginWithType:LSWaterFlowViewMarginTypeBottom]; contentH+=marginBottom; self.contentSize=CGSizeMake(0, contentH);}-(void)layoutSubviews{ [super layoutSubviews]; int count=self.cellFrames.count; for (int i=0; i<count; i++) { //在屏幕上 LSWaterFlowViewCell *cell=self.displayCells[@(i)]; CGRect frame=[self.cellFrames[i] CGRectValue]; if([self isOnScreenWithRect:frame]){ if (cell==nil) { cell=[self.dataSource waterFlowView:self cellForIndex:i]; cell.frame= frame; [self addSubview:cell]; //存放到记录显示在屏幕上的cell字典中 self.displayCells[@(i)]=cell; } } else{//不在屏幕上 if (cell) { //从字典中移除同时移除scrolllview [self.displayCells removeObjectForKey:@(i)]; [cell removeFromSuperview]; //加入缓存池 [self.reusableCells addObject:cell]; } } }}-(id)dequeueReusableCellWithIdentifier:(NSString *)identifier{ __block LSWaterFlowViewCell *reuseCell=nil; [self.reusableCells enumerateObjectsUsingBlock:^(LSWaterFlowViewCell * cell, BOOL * _Nonnull stop) { if ([cell.identifier isEqualToString:identifier]) { reuseCell=cell; *stop=YES; } }]; if (reuseCell) { [self.reusableCells removeObject:reuseCell]; } return reuseCell;}//计算是否在屏幕上-(BOOL)isOnScreenWithRect:(CGRect)rect{ return (CGRectGetMaxY(rect)>self.contentOffset.y)&&(CGRectGetMinY(rect)<self.contentOffset.y+self.frame.size.height);}-(void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ UITouch *touch=[touches anyObject]; CGPoint point=[touch locationInView:self]; __block NSNumber *selectedIndex=nil; [self.displayCells enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, LSWaterFlowViewCell* cell, BOOL * _Nonnull stop) { if (CGRectContainsPoint(cell.frame, point)) { selectedIndex=key; *stop=YES;} }]; if (selectedIndex) { if ([self.myDelegate respondsToSelector:@selector(waterFlowView:didSelectedAtIndex:)]) { [self.myDelegate waterFlowView:self didSelectedAtIndex:selectedIndex.integerValue]; } }
源代码地址http://download.csdn.net/detail/itiapp_home/9231281
相关文章
- RecyclerView实现瀑布流效果(图文详解+源码奉送)
- iOS开发-UICollectionView实现瀑布流
- 用jquery实现仿蘑菇街导航固定顶部的效果
- 使用Jquery的getJSON跨域请求蘑菇街图片资源实现瀑布流
- iOS开发UI篇—自定义瀑布流控件(蘑菇街瀑布流)
- android瀑布流效果(仿蘑菇街)
- 字节流与缓冲流,怎样实现高效率的?
- 视频流GPU解码在ffempg的实现(一)-基本概念
- 基于SqlSugar的开发框架循序渐进介绍(24)-- 使用Serialize.Linq对Lambda表达式进行序列化和反序列化 基于SqlSugar的开发框架循序渐进介绍(5)-- 在服务层使用接口注入方式实现IOC控制反转 基于SqlSugar的开发框架循序渐进介绍(7)-- 在文件上传模块中采用选项模式【Options】处理常规上传和FTP文件上传 基于SqlSugar的开发框架循序渐进介绍(12)-- 拆分页面模块内容为组件,实现分而治之的处理 基于SqlSugar的开发框架循序渐进介绍(14)-- 基于Vue3+TypeScript的全局对象的注入和使用 基于SqlSugar的开发框架循序渐进介绍(16)-- 工作流模块的功能介绍 基于SqlSugar的开发框架循序渐进介绍(17)-- 基于CSRedis实现缓存的处理 基于SqlSugar的开发框架循序渐进介绍(21)-- 在工作流列表页面中增加一些转义信息的输出,在后端进行内容转换 基于SqlSugar的开发框架循序渐进介
- php+jquery+ajax滚动条滚动到底部自动加载,简单实现瀑布流