瀑布流简单实现



使用scrollView简单实现瀑布流



代码实现

waterFlowView.h--------------------------------------

#import <UIKit/UIKit.h>


typedef enum {

    waterFiowViewMarginTypeTop,

    waterFiowViewMarginTypeBottom,

    waterFiowViewMarginTypeLeft,

    waterFiowViewMarginTypeRight,

    waterFiowViewMarginTypeColumn,//每一列

    waterFiowViewMarginTypeRow,  //每一行

    

}waterFiowViewMarginType;


@class waterFlowviewCell,waterFiowView;


//数据源方法

@protocol WaterFlowViewDataSource <NSObject>

//必须实现的方法

@required

//一共有多少个数据

- (NSUInteger)numberOfCellsInWaterFlowView:(waterFiowView *)waterFlowView;

//返回index位置对应的cell

- (waterFlowviewCell *)waterFlowView:(waterFiowView *)waterFlowView cellAtIndex:(NSUInteger)index;

@optional


//一共有多少列

- (NSUInteger)numberOfColumnsInWaterFlowView:(waterFiowView *)waterFlowView;

@end



//代理方法

@protocol WaterFlowViewDelegate <UIScrollViewDelegate>


@optional


//index位置cell对应的高度

- (CGFloat)waterFlowView:(waterFiowView *)waterFiowView heightAtIndex:(NSUInteger)index;

//选中第index位置的cell

- (void)waterFiowView:(waterFiowView *)waterFiowView didSelectAtIndex:(NSUInteger)index;


//返回间距

- (CGFloat)waterFiowView:(waterFiowView *)waterFiowView marginForType:(waterFiowViewMarginType)type;



@end



@interface waterFiowView :UIScrollView

@property(nonatomic,weak)id<WaterFlowViewDataSource>datasource;

@property(nonatomic,weak)id<WaterFlowViewDelegate>delegate;


- (CGFloat)cellWidth;


- (void)reloadData;


- (id)dequeuereusableCellWithIdentifier:(NSString *)indentifier;


@end

-----------------------------------


waterFlowView.m---------------------------------------------

#import "waterFiowView.h"

#import "waterFlowviewCell.h"

#define waterFlowViewDefaultNumberOfClunms 3

#define waterFiowViewDefaultCellH 100

#define waterFiowViewDefaultMargin 10



@interface waterFiowView()

@property(nonatomic,strong)NSMutableArray *cellFrames;


@property(nonatomic,strong)NSMutableDictionary *displayingcells;


@property(nonatomic,strong)NSMutableSet *reusableCells;

@end

-------------------------------------------

//1,计算每个cellframe

- (void)reloadData{

    

     _displayingcells = [NSMutableDictionarydictionary];

    

    //cell的总数是多少

    

   int numberOfCells = (int)[self.datasourcenumberOfCellsInWaterFlowView:self];

    //cell的列数

   int numberOfColumns = (int)[selfnumberOfColumns];

   //间距

    CGFloat leftM = [selfmarginForType:waterFiowViewMarginTypeLeft];

    CGFloat rightM = [selfmarginForType:waterFiowViewMarginTypeRight];

    CGFloat ColumnM = [selfmarginForType:waterFiowViewMarginTypeColumn];

    CGFloat topM = [selfmarginForType:waterFiowViewMarginTypeTop];

    CGFloat rowM = [selfmarginForType:waterFiowViewMarginTypeRow];

    CGFloat bottomM = [selfmarginForType:waterFiowViewMarginTypeBottom];

    

    

    //1cell的宽度

    //cell的宽度=(整个view的宽度-左边的间距-右边的间距-(列数-1x每列之间的间距)/总列数

    

   CGFloat cellW = (self.frame.size.width - leftM-rightM-(numberOfColumns-1)*ColumnM)/numberOfColumns;

    

    //用一个c语言的数组来存放所有列的最大y

   CGFloat maxYOfColumns[numberOfColumns];

   for (int i =0; i <numberOfColumns; i++) {

        //初始化数组的数值全部为0

        maxYOfColumns[i] =0;

    }

    

   //计算每个cellframe

    

   for (int i =0; i < numberOfCells ; i++) {

        //2cell的高度

        //i 位置的高度

       CGFloat cellH = [selfheightAtIndex:i];

        //cell处在第几列(最短的一列)

        

       NSUInteger cellAtColumn = 0;

        

        //cell所处那列的最大y值(当前最短的那一列的最大的y值)

        //默认设置最短的一列为第一列

        

       CGFloat maxYOfCellAtColumn = maxYOfColumns[cellAtColumn];

        //求出最短的那一列

       for (int j =0 ; j < numberOfColumns; j++) {

           if (maxYOfColumns[j]<maxYOfCellAtColumn) {

                cellAtColumn = j;

                maxYOfCellAtColumn = maxYOfColumns[j];

            }

        }

        

        //3cell的位置

        //cellx=左边的间距+列号*(cell的宽度+每列之间的间距)

        

       CGFloat cellX = leftM + cellAtColumn * (cellW +ColumnM);

        //celly,先设定为0

       CGFloat cellY = 0;

       if (maxYOfCellAtColumn == 0.0) {//首行

            cellY = topM;

        }else{

            

            cellY = maxYOfCellAtColumn + rowM;

            

        }

        //设置cellframe并添加到数组中去

        

       CGRect cellFrame = CGRectMake(cellX, cellY, cellW, cellH);

        [self.cellFramesaddObject:[NSValuevalueWithCGRect:cellFrame]];

        

        //更新最短那一列的最大的y

        maxYOfColumns[cellAtColumn] =CGRectGetMaxY(cellFrame);

        

//        waterFlowviewCell *cell = [self.datasource waterFlowView:self cellAtIndex:i];

//        cell.frame = cellFrame;

//        [self addSubview:cell];

        

        

    }

    

    //设置contentSize

   CGFloat contentH = maxYOfColumns[0];

   for (int i =0; i <numberOfColumns; i++) {

       if (maxYOfColumns[i] > contentH) {

            contentH = maxYOfColumns[i];

        }

    }

    contentH +=bottomM;

   self.contentSize =CGSizeMake(0, contentH);


   

}


--------

- (void)layoutSubviews{

    

    [superlayoutSubviews];

  

    

    //向数据源索要对应位置的cell

   NSUInteger numberOfCells = self.cellFrames.count;

    

   for (int i =0; i < numberOfCells; i++) {

        

        //取出i位置的frame

       CGRect cellFrame = [self.cellFrames[i]CGRectValue];

        //--------------------------------------------

        //优先从字典中出去i位置的cell

        waterFlowviewCell *cell =self.displayingcells[@(i)];

        //----------------------------------------------


       if ([self isInScreen:cellFrame]) {//在屏幕上

            

           // waterFlowviewCell *cell = self.displayingcells[@(i)];

           if (cell == nil) {

                

            cell = [self.datasourcewaterFlowView:selfcellAtIndex:i];

            cell.frame = cellFrame;

            //[self addSubview:cell];

                

               //存放在字典中

                

           self.displayingcells[@(i)] = cell;

               

                

                [selfaddSubview:cell];

        }

        }else{

           if (cell) {

                

           

                [cellremoveFromSuperview];

                [self.displayingcellsremoveObjectForKey:@(i)];

                

               //存放进缓存池

                [self.reusableCellsaddObject:cell];

            }

        

            

        }

        

    }

    NSLog(@"-----%ld",self.subviews.count);

}


-------------

- (id)dequeuereusableCellWithIdentifier:(NSString *)indentifier{

    

   __block waterFlowviewCell *reusableCell =nil;

    

    [self.reusableCellsenumerateObjectsUsingBlock:^(waterFlowviewCell *cell,BOOL *stop) {

       if([cell.identifierisEqualToString:indentifier]){

            

            reusableCell = cell;

            *stop =YES;

        }

    }];

    

     

   if (reusableCell) {

        [self.reusableCellsremoveObject:reusableCell];

    }

   return reusableCell;

    

    

}

------------
判断对应的cell在不再屏幕上;

- (BOOL)isInScreen:(CGRect)frame{

    

    return (CGRectGetMaxY(frame)>self.contentOffset.y) && (CGRectGetMinY(frame)<self.contentOffset.y+self.frame.size.height);

    

    

}

-------------------

- (CGFloat)marginForType:(waterFiowViewMarginType)type{

    

   if ([self.delegaterespondsToSelector:@selector(waterFiowView:marginForType:)]) {

        return [self.delegatewaterFiowView:selfmarginForType:type];

    }else{

        returnwaterFiowViewDefaultMargin;

    }

}

- (NSUInteger)numberOfColumns{

    

   if ([self.datasourcerespondsToSelector:@selector(numberOfColumnsInWaterFlowView:)]) {

        return [self.datasourcenumberOfColumnsInWaterFlowView:self];

    }else{

        returnwaterFlowViewDefaultNumberOfClunms;

    }

}

- (CGFloat)heightAtIndex:(NSUInteger)index{

   if ([self.delegaterespondsToSelector:@selector(waterFlowView:heightAtIndex:)]) {

        return [self.delegatewaterFlowView:selfheightAtIndex:index];

    }else{

        returnwaterFiowViewDefaultCellH;

    }

    

}

------------------------------------------
viewController.m

实现waterFlowView的DataSource和Delegate方法

- (waterFlowviewCell *)waterFlowView:(waterFiowView *)waterFlowView cellAtIndex:(NSUInteger)index{

    

   static NSString *inde =@"cell";

   waterFlowviewCell *cell = [waterFlowView dequeuereusableCellWithIdentifier:inde];

    

   if (cell == nil) {

        

        cell = [[waterFlowviewCellalloc] init];

        cell.identifier = inde;

        //cell.backgroundColor = [UIColor purpleColor];

       

       // [cell addSubview:[UIButton buttonWithType:UIButtonTypeContactAdd]];

        cell.backgroundColor = [UIColorcolorWithRed:arc4random()%10*.1green:arc4random()%10*.1 blue:arc4random()%10*.1 alpha:.1];

        

       UILabel *label = [[UILabelalloc] initWithFrame:CGRectMake(5,5, 25, 25)];

        label.tag =120;

        [celladdSubview:label];

    }

   UILabel *label = (UILabel *)[cellviewWithTag:120];

    label.text = [NSStringstringWithFormat:@"%ld",index];

    

   // NSLog(@"%ld--%p",index,cell);

   return cell;

}

- (CGFloat)waterFlowView:(waterFiowView *)waterFiowView heightAtIndex:(NSUInteger)index{

    

   switch (index%3) {

       case 0:

           return 90;

          

       case 1:

           return 110;

           

       case 2:

           return 80;

            

       default:

           return 120;

           

    }

}

- (CGFloat)waterFiowView:(waterFiowView *)waterFiowView marginForType:(waterFiowViewMarginType)type{

   switch (type) {

        casewaterFiowViewMarginTypeTop:

        casewaterFiowViewMarginTypeBottom:

        casewaterFiowViewMarginTypeLeft:

        casewaterFiowViewMarginTypeRight:

           return 10;

        casewaterFiowViewMarginTypeColumn:

        casewaterFiowViewMarginTypeRow:

           return 5;

    }

    

}

- (void)waterFiowView:(waterFiowView *)waterFiowView didSelectAtIndex:(NSUInteger)index{

    

    

    NSLog(@"点击了%ldcell",index);

}


-----------

运行效果




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值