UICollectionView 很简单的写个瀑布流

你项目中要用到它吗?

可能会在你的项目中用到这玩意,最近也是要用就简单的写了一个 Demo。没多少代码,就不放Git了,下面会详细点的说说代码的,要还有什么问题的小伙伴可以直接Q我,也可以把Demo发给你,这里有Q可以找一下加我 多多交流,互相学习!

下面是简单的一个效果图,先给看看效果图!

先说说控制器里面的代码,控制器里面就是我们的  UICollectionView  的一些基本的创建了。其实它和 UITableView 相比较的话,但从创建使用看的话,是挺相似的,但其实它真的比 UITableView 要强大好多!很值得大家去好好的学习学习!你要占我它的基本创建的话,可以参考 UITableView ,参考对比也有利于学习。

#import "ViewController.h"
#import "zxFlowLayout.h"
@interface ViewController  ()<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
{
    NSString * cellId;
}

@property(nonatomic,strong) UICollectionView * collectionview;
@end

@implementation ViewController

- (void)viewDidLoad {

    [super viewDidLoad];
    // Do any additional setup after loading the view.
    cellId = @"zhangxucell";
    self.view.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:self.collectionview];
    [_collectionview registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:cellId];

}

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 100;
}

// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{

    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath];
    cell.backgroundColor = [UIColor colorWithRed:arc4random()%255/255.0 green:arc4random()%255/255.0 blue:arc4random()%255/255.0 alpha:1];
    return cell;
}

-(UICollectionView * )collectionview
{
    if (!_collectionview) {

        zxFlowLayout * collectionLayout = [[zxFlowLayout alloc]init];
        [collectionLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
        collectionLayout.itemcount = 100;
        _collectionview = [[UICollectionView alloc]initWithFrame:self.view.bounds collectionViewLayout:collectionLayout];
        _collectionview.delegate = self;
        _collectionview.dataSource = self;
        _collectionview.backgroundColor = [UIColor whiteColor];

    }

    return _collectionview;
}

上面是Demo的控制器部分,要是对 UICollectionView 不怎么熟悉的话,你可以看看 这篇博客。觉得写得很不错,推荐给大家去学习,里面的内容很详细!

上面的控制器说完了,就到重点了,也就是继承与  UICollectionViewFlowLayout 的  zxFlowLayout ,有一点大家注意一下,就是你在初始化UICollectionView 的时候, [UICollectionView alloc]initWithFrame:(CGRect) collectionViewLayout:(nonnull UICollectionViewLayout *)  这个方法中,UICollectionViewLayout 这里需要的参数看上去是 UICollectionViewLayout 类型的,其实你创建的时候是要用继承与它的 UICollectionViewFlowLayout 对象去初始化的,这也就解释了我们的zxFlowLayout 是继承与 UICollectionViewFlowLayout 的!!不然你是不会看到 cell 的。有朋友以前说过这个,就特别提醒一下下吧。

#import "zxFlowLayout.h"

@implementation zxFlowLayout

// 数组相关的属性在这里重写
// 在布局之前会调用的这个方法
-(void)prepareLayout
{
    _attArray = [[NSMutableArray alloc]init];
    /**
     *  重写父类方法,这个记得要加进去!
     */
    // typeof 是一个一元运算,放在一个运算数之前,运算数可以是任意类型。
    // typedef

    [super prepareLayout];

    // 设计 item的宽度 设计3列或者2列
    float WIDTH = ([UIScreen mainScreen].bounds.size.width - self.minimumInteritemSpacing - self.sectionInset.left - self.sectionInset.right )/3;

    //定义数组保存每一列的高度
    //这个数组的主要作用是保存每一列的总高度,这样在布局时,我们可以始终将下一个Item放在最短的列下面,初始化值全都定义成零
    CGFloat colHight[3]={0,0,0};

    // 遍历传过来的 cell 设置属性
    for (int i =0; i<_itemcount; i++) {

        NSIndexPath * indexpath = [NSIndexPath indexPathForItem:i inSection:0];

        UICollectionViewLayoutAttributes * attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexpath];
        // 把高度控制在100 - 150 之间
        CGFloat Hight = arc4random()% 150 + 100;

        /**
         *   瀑布流是两行还是三行甚至再多行,你都可以在这里修改只是下面的判断就会相应的变化!
             我注释掉的是两行的!!!
         */
//        int width=0;
//        if (colHight[0]<colHight[1]) {
//
//            //将新的item高度加入到短的一列
//            colHight[0] = colHight[0]+Hight+self.minimumLineSpacing;
//            width=0;
//
//        }else{
//
//            colHight[1] = colHight[1]+Hight+self.minimumLineSpacing;
//            width=1;
//        }

        int width=0;
        if (i<3) {

                colHight[i] = colHight[i]+Hight+self.minimumLineSpacing;
                width = i;
        }
        else if ((colHight[0]<colHight[1]&&colHight[0]<colHight[2])||(colHight[0]<colHight[2]&&colHight[0]<colHight[1])) {
            //将新的item高度加入到短的一列
            colHight[0] = colHight[0]+Hight+self.minimumLineSpacing;
            width=0;
        }
        else if ((colHight[1]<colHight[0]&&colHight[1]<colHight[2])||(colHight[1]<colHight[2]&&colHight[1]<colHight[0]))
        {
            colHight[1] = colHight[1]+Hight+self.minimumLineSpacing;
            width=1;
        }
        else if ((colHight[2]<colHight[1]&&colHight[2]<colHight[0])||(colHight[2]<colHight[0]&&colHight[2]<colHight[1]))
        {

            colHight[2] = colHight[2]+Hight+self.minimumLineSpacing;
            width=2;
        }

        //设置item的位置
        attributes.frame = CGRectMake(self.sectionInset.left+(self.minimumInteritemSpacing+WIDTH)*width, colHight[width]-Hight-self.minimumLineSpacing, WIDTH, Hight);

        [_attArray addObject:attributes];

    }

//    设置itemSize来确保滑动范围的正确 这里是通过将所有的item高度平均化,计算出来的(以最高的列位标准)
//    if (colHight[0]>colHight[1]) {
//        self.itemSize = CGSizeMake(WIDTH, (colHight[0]-self.sectionInset.top)*2/_itemcount-self.minimumLineSpacing);
//    }else{
//        self.itemSize = CGSizeMake(WIDTH, (colHight[1]-self.sectionInset.top)*2/_itemcount-self.minimumLineSpacing);
//    }
//

    if (colHight[0]<colHight[1]<colHight[2]||colHight[0]<colHight[2]<colHight[1]) {

        self.itemSize = CGSizeMake(WIDTH, (colHight[0]-self.sectionInset.top)*2/_itemcount-self.minimumLineSpacing);
    }
    else if (colHight[1]<colHight[2]<colHight[0]||colHight[1]<colHight[0]<colHight[2])
    {
       self.itemSize = CGSizeMake(WIDTH, (colHight[1]-self.sectionInset.top)*2/_itemcount-self.minimumLineSpacing);
    }
    else{

        self.itemSize = CGSizeMake(WIDTH, (colHight[2]-self.sectionInset.top)*2/_itemcount-self.minimumLineSpacing);
    }

}

//-(UICollectionViewLayoutAttributes * )layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
//{
//    UICollectionViewLayoutAttributes * attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//
//    attributes.frame = CGRectMake(10, 10, (self.collectionView.frame.size.width-40)/3,100);
//
//    return attributes;
//}

// 返回设置了属性的数组
- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect
{

    return _attArray;
}

// return an array layout attributes instances for all the views in the given rect
@end

上面是整个.m 文件。 .h 文件里面也就只有  itemcount 这一个属性了,这个属性其实在你控制器当中你刷新完数据之后就传过来。让它重新布局就OK了!挺简单的对吧。。

最后,给小伙伴推荐一个 开源中国 社区的博主。声明我们俩真不认识??,我是看他在开源中国的博客写的挺好的,我最近有时间也是在仔细的看。就推荐给大家,相信还是能给大家带来许多可以学习的东西的。毕竟,我觉得在 唯品会 这种大一点的公司的程序猿,应该不会差!! 链接这里 自己经常逛各种社区博客,也是收藏了一些不错的博主的,要就联系me吧。。。??

时间: 2024-10-19 06:03:52

UICollectionView 很简单的写个瀑布流的相关文章

基于jquery和knockout.js 写个瀑布流异步加载分页

<div class="list-view"> <ul> <li data-bind="foreach:datalst"> <div class="item border clearfix"> <div class="face fl"> <a target="_blank" data-bind="attr:{'title':user

iOS开发:一个瀑布流的设计与实现(已实现缓存池功能,该功能使得瀑布流cell可以循环利用)

一个瀑布流的实现有三种方式: 继承自UIScrollView,仿写UITableView的dataSource和delegate,创造一个缓存池用来实现循环利用cell 写多个UITableview(UITableView的cell宽度是与UITableView宽度一样的,那么每行可以摆设多个宽度相等的UITableView,从而实现瀑布流),不过这种方法是最差的,因为不能有效的做到循环利用cell 可以自定义UICollectionViewCell的布局,从而实现瀑布流,UICollectio

OC-UICollectionView实现瀑布流

UICollectionView实现瀑布流 在iOS中可以实现瀑布流的目前已知的有2种方案: 使用UIScrollView自己封装一套,这种方案是应用于iOS6之前的,因为iOS6才出来UICollectionView,不过现在这种方案已经不怎么用了,还得自己封装.而且自己封装的性能不一定有系统的要好. 使用系统自带的UICollectionView,然后自定义layout,自己实现瀑布流效果 本文中我们介绍第二种实现方案首先我们需要自定义一个继承于UICollectionViewLayout的

iOS开发UI篇—自定义瀑布流控件(接口设计)

iOS开发UI篇—自定义瀑布流控件(接口设计) 一.简单说明 1.关于瀑布流 电商应用要展示商品信息通常是通过瀑布流的方式,因为每个商品的展示图片,长度和商都都不太一样. 如果不用瀑布流的话,展示这样的格子数据,还有一种办法是使用九宫格. 但利用九宫格有一个缺点,那就是每个格子的宽高是一样的,如果一定要使用九宫格来展示,那么展示的商品图片可能会变形. 为了保证商品图片能够按照原来的宽高比进行展示,一般采用的是瀑布流的方式. 2.瀑布流的特点: 由很多的格子组成,但是每个格子的宽度和高速都是不确定

瀑布流的原理

以前写过瀑布流,但对于其中某些概念和一些细节一直没理清,导致写代码时一直心存疑虑.没法用准确的代码来描述. 仅仅停留在我的代码能运行,但出了问题不好查. 昨天花近2小时理清了. var wuyu=1;...function roll(){ //scrollTop “卷”起来的高度值 var sTop = document.body.scrollTop || document.documentElement.scrollTop; //获取位于对象最顶端和窗口中可见内容的最顶端之间的距离 var c

UICollectionView的简单使用(二)— 瀑布流(石工布局)

有了上一篇的基础,发现现在常用UICollectionView的布局是瀑布流(石工布局),首先我看看默认大小不一的布局. 1.默认布局 我们在ViewController.m文件添加一下代码 - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)ind

IOS 瀑布流UICollectionView实现

IOS 瀑布流UICollectionView实现 在实现瀑布流之前先来看看瀑布流的雏形(此方法的雏形 UICollectionView) 对于UICollectionView我们有几点注意事项 它和tableView不一样,ContentView的内容完全需要我们自己去添加. 它与tableview相比,他的初始化需要FlowLayout并且大部分操作在其上. UIcollectionView的实用性极强,虽然有时他并不是最好的解决方案,但是它可以很灵活的实现各种效果. 图(一) 如图,模拟器

iOS开发之窥探UICollectionViewController(三) --使用UICollectionView自定义瀑布流

上篇博客的实例是自带的UICollectionViewDelegateFlowLayout布局基础上来做的Demo, 详情请看<iOS开发之窥探UICollectionViewController(二) --详解CollectionView各种回调>.UICollectionView之所以强大,是因为其具有自定义功能,这一自定义就不得了啦,自由度非常大,定制的高,所以功能也是灰常强大的.本篇博客就不使用自带的流式布局了,我们要自定义一个瀑布流.自定义的瀑布流可以配置其参数: 每个Cell的边距

iOS开发-UICollectionView实现瀑布流

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