美文网首页
iOS 瀑布流

iOS 瀑布流

作者: 画舫烟中浅 | 来源:发表于2020-04-13 18:06 被阅读0次

这是个人记录学习 ,想要详细了解的 。请参考文章:https://www.jianshu.com/p/2b9a73aefe28 这里面说的很详细。感谢大佬

1.首先自定义UICollectionViewFlowLayout

MyCustomFlowLayout.h 文件

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface MyCustomFlowLayout : UICollectionViewFlowLayout

@property (nonatomic,assign) CGFloat itemWith;
/**
 瀑布流布局方法

 @param itemWidth item 的宽度
@param itemHeightArray item 的高度数组
*/
- (void)flowLayoutWithItemWidth:(CGFloat)itemWidth itemHeightArray:(NSArray<NSNumber *> *)itemHeightArray;


@end

NS_ASSUME_NONNULL_END

MyCustomFlowLayout.m 文件

#import "MyCustomFlowLayout.h"

@interface MyCustomFlowLayout()

/**
item 的高度数组
*/
@property (nonatomic, copy) NSArray<NSNumber *> *arrItemHeight;

/**
 cell 布局属性集
*/
 @property (nonatomic, strong) NSArray<UICollectionViewLayoutAttributes *> *arrAttributes;

@end

@implementation MyCustomFlowLayout

- (void)flowLayoutWithItemWidth:(CGFloat)itemWidth itemHeightArray:(NSArray<NSNumber *> *)itemHeightArray {

self.itemSize = CGSizeMake(itemWidth, 0);
self.arrItemHeight = itemHeightArray;
[self.collectionView reloadData];
}

-(void)setItemWith:(CGFloat)itemWith{
_itemWith = itemWith;
}

- (void)prepareLayout {

[super prepareLayout];
// item 数量为零不做处理
if ([self.arrItemHeight count] == 0) {
    
    return;
}

// 计算一行可以放多少个项
NSInteger nItemInRow = (self.collectionViewContentSize.width - self.sectionInset.left - self.sectionInset.right + self.minimumInteritemSpacing) / (self.itemSize.width + self.minimumInteritemSpacing);
// 对列的长度进行累计
NSMutableArray *arrmColumnLength = [NSMutableArray arrayWithCapacity:100];
for (NSInteger i = 0; i < nItemInRow; i++) {
    
    [arrmColumnLength addObject:@0];
}

NSMutableArray *arrmTemp = [NSMutableArray arrayWithCapacity:100];
// 遍历设置每一个item的布局
for (NSInteger i = 0; i < [self.arrItemHeight count]; i++) {
    
    // 设置每个item的位置等相关属性
    NSIndexPath *index = [NSIndexPath indexPathForItem:i inSection:0];
    // 创建每一个布局属性类,通过indexPath来创建
    UICollectionViewLayoutAttributes *attris = [self layoutAttributesForItemAtIndexPath:index];
    CGRect recFrame = attris.frame;
    // 有数组得到的高度
    recFrame.size.height = [self.arrItemHeight[i] doubleValue];
    // 最短列序号
    NSInteger nNumShort = 0;
    // 最短的长度
    CGFloat fShortLength = [arrmColumnLength[0] doubleValue];
    // 比较是否存在更短的列
    for (int i = 1; i < [arrmColumnLength count]; i++) {

        CGFloat fLength = [arrmColumnLength[i] doubleValue];
        if (fLength < fShortLength) {

            nNumShort = i;
            fShortLength = fLength;
        }
    }
    // 插入到最短的列中
    recFrame.origin.x = self.sectionInset.left + (self.itemSize.width + self.minimumInteritemSpacing) * nNumShort;
    recFrame.origin.y = fShortLength + self.minimumLineSpacing;
    // 更新列的累计长度
    arrmColumnLength[nNumShort] = [NSNumber numberWithDouble:CGRectGetMaxY(recFrame)];
    
    // 更新布局
    attris.frame = recFrame;
    [arrmTemp addObject:attris];
}
self.arrAttributes = arrmTemp;

// 因为使用了瀑布流布局使得滚动范围是根据 item 的大小和个数决定的,所以以最长的列为基准,将高度平均到每一个 cell 中
// 最长列序号
NSInteger nNumLong = 0;
// 最长的长度
CGFloat fLongLength = [arrmColumnLength[0] doubleValue];
// 比较是否存在更短的列
for (int i = 1; i < [arrmColumnLength count]; i++) {

    CGFloat fLength = [arrmColumnLength[i] doubleValue];
    if (fLength > fLongLength) {

        nNumLong = i;
        fLongLength = fLength;
    }
}
// 在大小一样的情况下,有多少行
NSInteger nRows = ([self.arrItemHeight count] + nItemInRow - 1) / nItemInRow;
self.itemSize = CGSizeMake(self.itemSize.width, (fLongLength + self.minimumLineSpacing) / nRows - self.minimumLineSpacing);

}

// 返回所有的 cell 布局数组
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect {

return self.arrAttributes;
}

@end
  1. 调用方法
#define  kScreenWidth  [UIScreen mainScreen].bounds.size.width
#define kScreenHeight [UIScreen mainScreen].bounds.size.height

#import "WalltViewController.h"
#import "MyCustomFlowLayout.h"
#import "Masonry.h"
@interface WalltViewController ()<UICollectionViewDelegate,UICollectionViewDataSource>

@property (nonatomic , strong) UICollectionView *collection;
@property (nonatomic , strong) MyCustomFlowLayout *myLayout;
@property (nonatomic , strong) NSMutableArray *arrmHeight;

@end
 static NSString *cellId = @"custom_cell";
@implementation WalltViewController

- (void)viewDidLoad {
   [super viewDidLoad];

self.view.backgroundColor = [UIColor whiteColor];

self.myLayout = [[MyCustomFlowLayout alloc] init];
// 以最小间距为10计算间距
// 每行可放多少 cell
self.myLayout.itemWith = 150;
NSInteger nCountCell = (kScreenWidth - 10) / (self.myLayout.itemWith + 10);
// 平均后的间距
CGFloat fSpacing = (kScreenWidth - self.myLayout.itemWith * nCountCell) / (nCountCell + 1);
self.myLayout.minimumInteritemSpacing = fSpacing;
self.myLayout.minimumLineSpacing = fSpacing;
self.myLayout.sectionInset = UIEdgeInsetsMake(fSpacing, fSpacing, fSpacing, fSpacing);
// 创建随机高度的数组
_arrmHeight = [NSMutableArray array];
   dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
       for (int j=0; j<40; j++) {
          if (j % 4 == 0) {
            [_arrmHeight addObject:[NSNumber numberWithFloat:190.0]];
          }else if (j % 4 == 1){
            [_arrmHeight addObject:[NSNumber numberWithFloat:260.0]];
          }else if (j % 4 == 2){
           [_arrmHeight addObject:[NSNumber numberWithFloat:260.0]];
          }else if (j % 4 == 3){
            [_arrmHeight addObject:[NSNumber numberWithFloat:190.0]];
          }
       }
       [self.myLayout flowLayoutWithItemWidth:150 itemHeightArray:_arrmHeight];
     
  });


_collection = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 64, kScreenWidth, kScreenHeight - 64) collectionViewLayout:self.myLayout];
_collection.backgroundColor = [UIColor whiteColor];
_collection.delegate = self;
_collection.dataSource = self;
[self.view addSubview:_collection];

// 注册 cell
[_collection registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:cellId];
}

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

UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath];

for (UIView *view in cell.contentView.subviews) {
    [view removeFromSuperview];
}
CGFloat height = [_arrmHeight[indexPath.item] floatValue]-70;
UIImageView *imageView = [[UIImageView alloc] init];
imageView.frame = CGRectMake(0, 0, 150, height);
imageView.backgroundColor = [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1];
[cell.contentView addSubview:imageView];

UILabel *label = [[UILabel alloc] init];
label.text = @"拟把疏狂图一醉,对酒当歌,强乐还无味,衣带渐宽终不悔,为伊消得人憔悴";
label.textColor = [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1];
label.font = [UIFont systemFontOfSize:16];
label.textAlignment = NSTextAlignmentLeft;
[cell.contentView addSubview:label];
[label mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.mas_equalTo(cell.contentView);
    make.right.mas_equalTo(cell.contentView);
    make.top.equalTo(imageView.mas_bottom).offset(5);
    make.height.mas_equalTo(20);
}];

UIImageView *iconImageV = [[UIImageView alloc] init];
iconImageV.image = [UIImage imageNamed:@"h7"];
[cell.contentView addSubview:iconImageV];
[iconImageV mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.mas_equalTo(cell.contentView);
    make.top.equalTo(label.mas_bottom).offset(5);
    make.size.mas_equalTo(CGSizeMake(40, 40));
}];
iconImageV.layer.cornerRadius = 20;
iconImageV.layer.masksToBounds = YES;

UILabel *nameLabel = [[UILabel alloc] init];
nameLabel.text = @"青平乐";
nameLabel.textColor = [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1];
nameLabel.font = [UIFont systemFontOfSize:13];
nameLabel.textAlignment = NSTextAlignmentCenter;
[cell.contentView addSubview:nameLabel];
[nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(iconImageV.mas_right).offset(20);
    make.centerY.mas_equalTo(iconImageV);
    make.width.mas_equalTo(40);
    make.height.mas_equalTo(20);
}];
return cell;
}

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

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

return _arrmHeight.count;
}

相关文章

  • iOS UICollectionView autolayout

    iOS UICollectionView autolayout UICollectionViewCell 瀑布流加...

  • 关于自定义瀑布流的布局(Swift)

    瀑布流 UICollectionView Swift 最近整理以前iOS开发中用到的功能代码,发觉对瀑布流的布局有...

  • iOS使用UICollectionView实现瀑布流

    UICollectionView实现瀑布流 在iOS中可以实现瀑布流的目前已知的有2种方案: 使用UIScroll...

  • iOS瀑布流

    说来惭愧,使用collectionView这么久了,还从来没自己写过瀑布流,废话不多说,先上效果图: 数据来源 数...

  • iOS瀑布流

    参考 http://blog.csdn.net/yi_zz32/article/details/50520136将...

  • iOS - 瀑布流

    在最近小玩一下瀑布流中发现的一个小坑如图: Demo下载:WaterFall - 瀑布流布局

  • iOS瀑布流

    瀑布流 因为iOS提供UICollectionViewLayout的布局类不能实现瀑布流的效果,所以需要自定义一个...

  • iOS 瀑布流

    下面这些是外部封装的接口: @interface LRBWaterFallLayout : UICollectio...

  • iOS瀑布流

    瀑布流Demo 使用UICollectionView实现瀑布流 自定义UICollectionViewLayout...

  • iOS 瀑布流

    1.简单认识 瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条...

网友评论

      本文标题:iOS 瀑布流

      本文链接:https://www.haomeiwen.com/subject/irpnmhtx.html