重复利用的瀑布流视图

Step1 ===封装自定义的UIScrollView控制器

1 协议代理方法

1>>数据源代理PollScrollDataSource
@protocol PollScrollDataSource <NSObject>
@required
//返回总列数
- (NSInteger)numberOfColums:(UIScrollView *)jrScroll;
//返回cell总个数
- (NSInteger)numberOfCells:(UIScrollView *)jrScroll;
//返回每个cell的实际宽高
- (CGSize)sizeOfCellInScroll:(UIScrollView *)jrScroll cellAtIndex:(NSInteger)index;
//返回cell视图
- (UIView *)jrScroll:(UIScrollView *)jrScroll cellAtIndex:(NSInteger)index;
@end

2>>属性代理PollScrollDelegate
@protocol PollScrollDelegate <NSObject>
@optional
//返回行间距
- (CGFloat)rowOfScroll:(UIScrollView *)jrScroll spaceForCellWithFlag:(PollScrollSpace)jrSpace;
@end

3>>定义代理
@property(nonatomic,weak)id <PollScrollDataSource> pollDataSource;
@property(nonatomic,weak)id <PollScrollDelegate> pollDelegate;

2 瀑布流视图,计算每个cell的位置大小

1>>由代理方法得到获取的每个cell大小位置
//枚举类型设置边距
#define kSpace 10
typedef enum {
    topScrollSpace,//上边距
    bottomScrollSpace,//下边距
    leftScrollSpace,//左边距
    rightScrollSpace,//右边距
    rowScrollSpace,//行边距
    columnScrollSpace//列边距   
}PollScrollSpace;

 //获取cell总数
    NSInteger totalCell=[self.pollDataSource numberOfCells:self];
    //获取总列数--如果列=0,则返回默认值3
    NSInteger totalColum=[self.pollDataSource numberOfColums:self];
    if (!totalColum) {
        totalColum=3;
    }

    //获取上、下、左、右、行、列间距---如果没有响应实现代理方法,设置默认值
    CGFloat topSpace=kSpace,bottomSpace=kSpace,leftSpace=kSpace,rightSpace=kSpace,rowSpace=kSpace,columnSpace=kSpace;
    if ([self.pollDelegate respondsToSelector:@selector(rowOfScroll:spaceForCellWithFlag:)]) {

        topSpace=[self.pollDelegate rowOfScroll:self spaceForCellWithFlag:topScrollSpace];
        bottomSpace=[self.pollDelegate rowOfScroll:self spaceForCellWithFlag:bottomScrollSpace];
        leftSpace=[self.pollDelegate rowOfScroll:self spaceForCellWithFlag:leftScrollSpace];
        rightSpace=[self.pollDelegate rowOfScroll:self spaceForCellWithFlag:rightScrollSpace];
        rowSpace=[self.pollDelegate rowOfScroll:self spaceForCellWithFlag:rowScrollSpace];
        columnSpace=[self.pollDelegate rowOfScroll:self spaceForCellWithFlag:columnScrollSpace];    
    }

    CGFloat coorArray[totalColum];
    for (int i=0; i<totalColum; i++) {//重新把数组初始化一下
        coorArray[i]=0;
    }
    for (int i=0;i<totalCell; i++) { 
        //计算所有frame
        //找到最低的位置
        CGFloat height=coorArray[0];
        NSInteger index=0;
        for(int j=0; j<totalColum; j++){
            if (coorArray[j] < height) {
                height=coorArray[j];
                index=j;
            }
        }

        //计算frame
        //获取实际图像的宽高,是从plist里面得到的实际宽、高
        CGSize frame=[self.pollDataSource sizeOfCellInScroll:self cellAtIndex:i];
        //设置每一个cell的宽高
        self.cellWidth=((self.frame.size.width-leftSpace-rightSpace)-columnSpace*(totalColum-1))/totalColum;
        self.cellHeight=self.cellWidth*frame.height/frame.width;//w h 由间距确定宽度,然后等比例缩放得到高度

        //相邻cell之间的间距
        CGFloat vSpace=self.cellHeight+rowSpace;//两个纵向cell之间的距离
        CGFloat hSpace=self.cellWidth+columnSpace;//两个横向cell距离
  //每一个cell所在的位置
        CGRect frames=CGRectMake(index*hSpace+leftSpace,height+rowSpace,self.cellWidth,self.cellHeight);
        NSValue * value=[NSValue valueWithCGRect:frames];
            ///更新数组数据
        coorArray[index]=CGRectGetMaxY(frames);
        [self.frameArray addObject:value];

    }

    //获取最大的height
    CGFloat maxHeight=coorArray[0];
    for (int j=0; j<totalColum; j++) {
        if (coorArray[j]>maxHeight) {
            maxHeight=coorArray[j];
        }
    }
self.contentSize=CGSizeMake(0, maxHeight+10);

3 可以重复利用的瀑布流视图

1>>渲染瀑布流视图方法
- (void)layoutSubviews{

    [super layoutSubviews];

    for (int i=0; i<self.frameArray.count; i++) {

        NSValue * value=self.frameArray[i];
        CGRect frame=[value CGRectValue];

        BOOL isInScreen=[self _isInScreen:frame];
        if(isInScreen){
            //在屏幕上时有两种情况---1>之前已经添加过(不做处理)--2>刚进入屏幕的(加入字典)
            if(!self.inScreenDic[@(i)]){//之前不在屏幕出现的加入字典

                UIView * view=[self.pollDataSource jrScroll:self cellAtIndex:i];
                view.frame=frame;

                [self addSubview:view];//加载到视野屏幕上
                [self.inScreenDic setObject:view forKey:@(i)];//加入到字典

            } 
        }
        else{
            //如果从屏幕上离开,从屏幕父视图上移除并且从字典中删除
            UIView * cell=self.inScreenDic[@(i)];

            if(jrCell){
                //加入到缓存池
                NSMutableSet * set=self.poolDic[jrCell.identy];
                [set addObject:jrCell];

                [jrCell removeFromSuperview];//从屏幕移除
                [self.inScreenDic removeObjectForKey:@(i)];//从字典删除
            }
        }
    }
}

2>>判断是不是在屏幕上
- (BOOL)_isInScreen:(CGRect)frame{
    CGFloat contentY=self.contentOffset.y;
    BOOL condition=CGRectGetMaxY(frame)>contentY && frame.origin.y<contentY+self.frame.size.height;
    return condition;
}

4 获取可以重复利用的cell视图

- (UIView *)dequeueReuseCellWithIdenty:(NSString *)identy{
    NSMutableSet * set=self.poolDic[identy];
    if (set==nil) {
        set=[NSMutableSet set];
        [self.poolDic setObject:set forKey:identy];
    }
    UIView * view=[set anyObject];
    if (view) {
        [set removeObject:view];
    }
    return view;
}

Step2 ===瀑布流实现

1>>加载数据(plist文件)
- (void)_loadData{

    //从plist里面获取数据存入到数组
    NSString * path=[[NSBundle mainBundle]pathForResource:@"file.plist" ofType:nil];
    self.dataArray=[NSArray arrayWithContentsOfFile:path];
}

2>>调用所定义的UIScrollView,实现代理
- (void)_loadSubviews{

    UIScrollView * scrollView=[[UIScrollView alloc]initWithFrame:self.view.bounds];
    scrollView.pollDataSource=self;
    scrollView.pollDelegate=self;
    self.scrollView=scrollView;
    [self.view addSubview:scrollView];  
}

3>>代理方法
#pragma mark - PollDataSource
//返回总列数
- (NSInteger)numberOfColums:(UIScrollView *)jrScroll{
    return 3;
}

//返回cell总个数
- (NSInteger)numberOfCells:(UIScrollView *)jrScroll{
    return self.dataArray.count;
}

//返回每个cell的实际宽高
- (CGSize)sizeOfCellInScroll:(UIScrollView *)jrScroll cellAtIndex:(NSInteger)index{

    NSDictionary * temDic=self.dataArray[index];
    self.width=[temDic[@"w"] floatValue];
    self.height=[temDic[@"h"] floatValue];
    return CGSizeMake(self.width, self.height);
}

//返回cell视图
- (UIView *)jrScroll:(UIScrollView *)jrScroll cellAtIndex:(NSInteger)index{

    static NSString * identy=@"myCell";
    UIView * cell=[jrScroll dequeueReuseCellWithIdenty:identy];//创建可以重复循环利用的cell
    if(cell==nil){
        cell=[[UIView alloc]initWithReuseIdentifier:identy];
//        NSLog(@"====>%li",index);
    }
    NSDictionary * dic=self.dataArray[index];
    cell.imgSrc=dic[@"img"];
    cell.textLabel.text=dic[@"price"];
    return cell;
}

#pragma mark - PollDelegate
//返回行间距
- (CGFloat)rowOfScroll:(UIScrollView *)jrScroll spaceForCellWithFlag:(PollScrollSpace)jrSpace{
    switch (jrSpace) {
        case topScrollSpace:
            return 20;
        case bottomScrollSpace:
            return 10;
        case leftScrollSpace:
            return 10;
        case rightScrollSpace:
            return 10;
        case rowScrollSpace:
            return 10;
        case columnScrollSpace:
            return 10;
        default:
            return 10;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值