iOS - 关于瀑布流3.0的实现

本文主要介绍如何在iOS中实现瀑布流布局,通过创建自定义布局ZJJCustomLayout,以及ZJJCustomModel和ZJJCustomCollectionCell,详细阐述瀑布流3.0的实现过程。在ViewController中设置和应用布局,最终达到理想的展示效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

只是说明实现瀑布流的方法, 以及自定义layout布局,其他多余事情本文不提。

先看项目框架:

1.ZJJCustomModel 类的内容

#import <Foundation/Foundation.h>



@interface ZJJCustomModel : NSObject

+ (NSArray *)customGetTheImagesArray;

@end
 
#import "ZJJCustomModel.h"



@implementation ZJJCustomModel

+ (NSArray *)customGetTheImagesArray {

    

//    0-30.jpg

    

    NSMutableArray *arr = [NSMutableArrayarrayWithCapacity:0];

    

    for (NSInteger i =0; i<31; i++) {

        

        NSString *name = [NSStringstringWithFormat:@"%ld.jpg",i];

        

        [arr addObject:name];

        

    }

    

    return arr;

    

}

@end

 

2.自定义cell(ZJJCustomCollectionCell)类

#import <UIKit/UIKit.h>



@interface ZJJCustomCollectionCell : UICollectionViewCell



- (id)initWithFrame:(CGRect)frame;



// 自定义 cell 的 label 和 image

@property (nonatomic,strong) UILabel *label;

@property (nonatomic,strong) UIImageView *imageView;



// 图片名字和文本名字

@property (nonatomic,copy)    NSString *imageName;

@property (nonatomic,copy)    NSString *labelName;



@end
 
#import "ZJJCustomCollectionCell.h"



@implementation ZJJCustomCollectionCell



- (id)initWithFrame:(CGRect)frame {

    

    self = [super initWithFrame:frame];

    

    if (self) {

        

        self.backgroundColor = [UIColor colorWithRed:arc4random()%256/255.0 green:arc4random()%256/255.0 blue:arc4random()%256/255.0 alpha:1];

        

        self.imageView = [[UIImageView alloc] init];

        self.label = [[UILabel alloc] init];

        

        [self addSubview:self.imageView];

        [self addSubview:self.label];

    }

    return self;

}



- (void)setImageName:(NSString *)imageName {

    self.imageView.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);

    self.imageView.contentMode = UIViewContentModeScaleAspectFit;

    self.imageView.image = [UIImage imageNamed:imageName];

}



- (void)setLabelName:(NSString *)labelName {

    self.label.frame = CGRectMake(0, self.frame.size.height-30, self.frame.size.width, 30);

    self.label.backgroundColor = [UIColor greenColor];

    self.label.textColor = [UIColor redColor];

    self.label.text = labelName;

    self.label.textAlignment = NSTextAlignmentCenter;

}





@end
 

3.ViewController 类

// 重用cell标识符

#define   REUSE_CELL   @"cell"



#import "ViewController.h"

#import "ZJJCustomLayout.h"

#import "ZJJCustomModel.h"

#import "ZJJCustomCollectionCell.h"



@interface ViewController ()<UICollectionViewDataSource,UICollectionViewDelegateFlowLayout> {

    UICollectionView *_collect;

    NSArray *_dataArray;  // 数据源

}



@end



@implementation ViewController



- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    self.view.backgroundColor = [UIColor whiteColor];

    

    [self arrayInfo];

    

}

#pragma mark - 基础配置

- (void)creatView {

    

    ZJJCustomLayout *layout = [[ZJJCustomLayout alloc] init];

    layout.itemCount = _dataArray.count;

    layout.scrollDirection = UICollectionViewScrollDirectionVertical;

    

    _collect = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];

    _collect.backgroundColor = [UIColor whiteColor];

    _collect.delegate = self;

    _collect.dataSource = self;

    [_collect registerClass:[ZJJCustomCollectionCell class] forCellWithReuseIdentifier:REUSE_CELL];

    [self.view addSubview:_collect];

    

}

#pragma mark - 获取数据,填充数据源

- (void)arrayInfo {

    

    _dataArray = [ZJJCustomModel customGetTheImagesArray];

    

    [self creatView];



}

#pragma mark - collectionView 代理方法

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {

    return _dataArray.count;

}



- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    

    ZJJCustomCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:REUSE_CELL forIndexPath:indexPath];

    

    cell.imageName = _dataArray[indexPath.row];

    cell.labelName = [NSString stringWithFormat:@"总价:%ld元",indexPath.row+1];

    

    return cell;

}



- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {

    return 1;

}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {

    

    NSLog(@"点击了第%ld个item",indexPath.row);

    

    

}

- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}





@end
 

4.ZJJCustomLayout 类

 

#import <UIKit/UIKit.h>



@interface ZJJCustomLayout : UICollectionViewFlowLayout



@property (nonatomic, assign)   NSInteger itemCount; //元素个数



@end
 
#define   SCREEN_W    [UIScreen mainScreen].bounds.size.width

#define   SCREEN_H    [UIScreen mainScreen].bounds.size.height



#import "ZJJCustomLayout.h"



@interface ZJJCustomLayout () {

    

    float _itemW;   // 元素宽度

    

    float _itemH;    // 元素高度

    

    float _heightArray[3];  // 记录每列高度的数组,这里的瀑布流规定有三列

    

    NSMutableArray *_attributesMArray;   // 装有item属性的数组

}



@end





@implementation ZJJCustomLayout





- (void)prepareLayout {

    

    [super prepareLayout];

    

    // 这里假设有三列,给每列赋初始值(状态栏高度)

    _heightArray[0] = 20.0f;

    _heightArray[1] = 20.0f;

    _heightArray[2] = 20.0f;



    _attributesMArray = [NSMutableArray array];

    [_attributesMArray removeAllObjects];

    

    // 内外间隔是 10 ,可以设置每个元素的固定宽度

    _itemW = (SCREEN_W-10*(1+3))/3;

    

    for (NSInteger i = 0; i<_itemCount; i++) {

        // 随机给高度

        _itemH = arc4random()%50 + _itemW + 30;

        

        // 每个元素的横纵坐标

        float itemX = 0.0f;

        float itemY = 0.0f;

        

        /**

         记录 当前元素应该放在哪一列

         columnRecord = 0  ,  1  ,  2   

         分别表示应该放在 第  1  ,   2   ,3  列

        */

        int columnRecord = 0;



        if (i == 0) {

            columnRecord = 0;

        }else if (i == 1) {

            columnRecord = 1;

        }else if (i == 2) {

            columnRecord = 2;

        }else {

            // 找到最矮的

            if (_heightArray[0] > _heightArray[1]) {

                

                if (_heightArray[1] > _heightArray[2]) {

                    columnRecord = 2;

                }else {

                    columnRecord = 1;

                }

            }else {

                if (_heightArray[0] > _heightArray[2]) {

                    columnRecord = 2;

                }else {

                    columnRecord = 0;

                }

            }



        }

        

        if (columnRecord == 0) {

            itemX = 10;

            itemY = _heightArray[0];



            // 上下间隔 5 ,不要那么紧凑 

            _heightArray[0] += _itemH + 5;

        }else if (columnRecord == 1) {

            itemX = 10 + _itemW+10;

            itemY = _heightArray[1];



            _heightArray[1] += _itemH + 5;

        }else {

            itemX = (10+_itemW)*2+10;

            itemY = _heightArray[2];



            _heightArray[2] += _itemH + 5;

        }

        

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

        

         UICollectionViewLayoutAttributes *attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];

        

        attributes.frame = CGRectMake(itemX, itemY, _itemW, _itemH);

        

        [_attributesMArray addObject:attributes];

        

    }

    

}





- (nullable NSArray<__kindof UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {

    

    return _attributesMArray;

    

}



- (CGSize)collectionViewContentSize {

    

    float totalHeight = 0.0f;

    

    if (_heightArray[0] > _heightArray[1]) {

        

        totalHeight = MAX(_heightArray[0], _heightArray[2]);

        

    }else {

        

        totalHeight = MAX(_heightArray[1], _heightArray[2]);

        

    }

    

    return CGSizeMake(SCREEN_W, totalHeight);

    

}



@end
 

到此,就实现waterfall了,效果如下

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值