重复利用的瀑布流视图

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 * [email protected]"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;
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-15 03:09:45

重复利用的瀑布流视图的相关文章

ios图片瀑布流代码

ios瀑布流,实现简单的瀑布流视图布局,可以显示网络图片,下拉刷新,上拉加载更多. 下载:http://www.huiyi8.com/sc/9087.html ios图片瀑布流代码,布布扣,bubuko.com

自定义控件三部曲视图篇(三)——瀑布流容器WaterFallLayout实现

前言:只要在前行,梦想就不再遥远 系列文章: Android自定义控件三部曲文章索引:http://blog.csdn.net/harvic880925/article/details/50995268 前面两节讲解了有关ViewGroup的onMeasure.onLayout的知识,这节我们深入性地探讨一下,如何实现经常见到的瀑布流容器,本节将实现的效果图如下: 从效果图中可以看出这里要完成的几个功能: 1.图片随机添加 2.在添加图片时,总是将新图片插入到当前最短的列中 3.每个Item后,

PSCollectionView瀑布流实现

[-] 一基本原理 二具体实现 相关数据结构 视图更新方式 relayoutViews方法 removeAndAddCellsIfNecessary方法 select方法 重用数据块视图机制 三使用方法 四其他瀑布流实现 PSCollectionView是一个实现较简洁的仿Pinterest瀑布流iOS版实现,使用UIScrollView做容器,每列列宽固定,高度可变,使用方式类似UITableView.其效果如图: 一.基本原理 其基本实现原理为: 列数固定,根据列数每列存储一个当前列的高度值

自定义UICollectinviewFlowLayout,即实现瀑布流

如图所示,通过实现不规则的网格分布,来显示出不同的效果.因为集合视图必须要指定布局还可以显示,所以自定义布局就可以实现瀑布流的效果. //创建布局对象 WaterFlowLayout *flowLayout = [[WaterFlowLayout alloc] init]; flowLayout.delegate = self; flowLayout.numberOfColumn = 3; //创建集合视图 UICollectionView *collectionView = [[UIColle

使用RecyclerView实现瀑布流的效果

主函数: public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private List<String> dataList = new ArrayList<String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceS

瀑布流框架的搭建

瀑布流大家都应该熟悉了,现在大部分电商应用中或多或少的都用到瀑布流,它可以吸引用户的眼球,使用户不易产生视觉疲劳,苹果在iOS6中增添了UICollectionView控件,这个控件可以说是UITableView的升级版,通过这个控件我们就能很简单的做出瀑布流,后面通过自己的封装可以让其变成一个小框架,更简单的应用到我们之后的开发中 最近开通了简书欢迎大家关注,我会不定期的分享我的iOS开发经验  点击关注-->Melody_Zhy 如果想做瀑布流,那么就要自定义CollectionViewFl

UICollectionView创建瀑布流

UICollectionView与UITableView类似,它们的用法也差不多,所有的实现都是通过delegate以及dataSource来完成的,都有几个必须实现的协议,为以下协议. - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return 1; } - (NSInteger)collectionView:(UICollectionView *)collectionVie

iOS开发-UICollectionView实现瀑布流

关于瀑布流的实现网上有很多种解法,自定义控件,TableView+ScrollView,UICollectionView是iOS6发布之后用于展示集合视图,算起来已经发布三年左右了,不过知识点是不变的,集合视图提供了一个更优雅的方式去展示图片或者文字信息.UICollectionView与UITableView相似,UICollectionViewController与UITableViewController都负责视图,存储需要的数据,并且能处理数据源与委托协议. 简单瀑布流 首先来看一个简单

[iOS高级] UICollectionView实现瀑布流效果

UICollectionView在2012年被提出,已经不是什么新技术了,在此只是做一下简单的实现. 集合视图:UICollectionView UICollectionView和UITableView类似,它也是datasource和delegate设计模式的:datasource为view提供数据源,告诉view要显?示些什么东?以及如何显示它们,delegate提供一些样式的?细节以及?户交互的响应. 在collectionView中,对于cell的布局比较复杂,专?使?了?个类来对col