蘑菇街瀑布流的实现

时间:2021-11-01 00:37:20
蘑菇街利用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
蘑菇街瀑布流的实现

相关文章