IOS-—UICollectionView使用综述(二 )(基础篇--画廊展示图片,瀑布流展示图片)


效果图 :

画廊:


瀑布流:


1、画廊 

1.1 简述 

    这里是通过纯代码的方式进行添加操作

1.2 创建设置UICollectionView 

#import "ViewController.h"
#import "AppCell.h"
#import "AppFlowLayout.h"

@interface ViewController ()<UICollectionViewDataSource>

@end
//重用标识符
static NSString *identifier = @"cell";

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    //实例化一个自定义Flowlayout
    AppFlowLayout *flowlayout = [[AppFlowLayout alloc]init];
    
    //实例化创建一个CollectionView
    UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0
, 200, 375, 300) collectionViewLayout:flowlayout];

    //设置数据源代理
    collectionView.dataSource = self;
    
    
    //注册Cell

    [collectionView registerClass:[AppCell class] forCellWithReuseIdentifier:identifier];
    
    //添加到控制器上
    [self.view addSubview:collectionView];
}



//组
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
    return 1;
}
//行
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    return 10;
}
//内容
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    AppCell *collection =[collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
    
    return collection;
}

@end


1.3 自定义Cell 

AppCell.h 

#import <UIKit/UIKit.h>

@interface AppCell : UICollectionViewCell

@end


AppCell.m 

#import "AppCell.h"

@implementation AppCell

-(instancetype)initWithFrame:(CGRect)frame{
    if (self =[super initWithFrame:frame]) {
        //初始化创建UIImageView
        UIImageView *imageView =[[UIImageView alloc]initWithFrame:self.contentView.bounds];
        //设置默认图片
        imageView.image = [UIImage imageNamed:@"aqs"];
        [self.contentView addSubview:imageView];
        
    }
    return self;
} 
@end


1.4 自定义流式布局 

AppFlowLayout.h 

#import <UIKit/UIKit.h>

@interface AppFlowLayout : UICollectionViewFlowLayout

@end


AppFlowLayout.m

#import "AppFlowLayout.h"

@implementation PhotoFlowLayout

//在这个方法中,UICollectionView还没有实例化,所以取不到其对应的frame
-(instancetype)init{
    if (self == [super init]) {
       
    }
    return self;
}
//当布局刷新的时候会自动调用这个方法
-(void)prepareLayout{
    [super prepareLayout];
    //修改滚动方向 为水平方向来滚动
    self.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    //获取对应UICollectionView的Size
    CGSize collectionSize = self.collectionView.frame.size;
    
    //定义显示ITEM的 宽 高
    CGFloat itemWidth = collectionSize.height*0.6;
    CGFloat itemHeight = collectionSize.height*0.8;
    
    //修改ITEM大小
    self.itemSize = CGSizeMake(itemWidth, itemHeight);

    //设置头部和尾部的初始间距
    CGFloat topMargin = collectionSize.width/2-itemWidth/2;
    self.sectionInset = UIEdgeInsetsMake(0, topMargin, 0, topMargin);

}

//返回所的有的Item对应的属性设置
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
    //取出所有的Item对应的属性
    NSArray *superAttributesArray = [super layoutAttributesForElementsInRect:rect];
    
    //计算中心点
    CGFloat screenCenter = self.collectionView.contentOffset.x+self.collectionView.frame.size.width/2;
    //循环设置Item 的属性
    
    for (UICollectionViewLayoutAttributes  *attributes in superAttributesArray) {
        //计算 差值
        CGFloat deltaMargin = ABS(screenCenter - attributes.center.x);
        //计算放大比例
        CGFloat scale = 1 - deltaMargin/(self.collectionView.frame.size.width/2+attributes.size.width);
        //设置
        attributes.transform = CGAffineTransformMakeScale(scale, scale);
    }
    return superAttributesArray;
}

//当手指离开屏幕时会调用此方法
-(CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity{
    //取出屏幕的中心点
    CGFloat screenCenter = proposedContentOffset.x +self.collectionView.frame.size.width/2;
    //取出可见范围内的Cell
    CGRect visibleRect = CGRectZero;
    visibleRect.size = self.collectionView.frame.size;
    visibleRect.origin = proposedContentOffset;
    
    NSArray *visibleArray = [super layoutAttributesForElementsInRect:visibleRect];
    
    CGFloat minMargin = MAXFLOAT;
    
    for (UICollectionViewLayoutAttributes *attributes in visibleArray) {
        CGFloat deltaMargin = attributes.center.x -screenCenter;
        if (ABS(minMargin)>ABS(deltaMargin)) {
            minMargin = deltaMargin;
        }
    }
    return CGPointMake(proposedContentOffset.x+ minMargin, proposedContentOffset.y);
}

//当屏幕的可见范围发生变化 的时候
//重新刷新视图
-(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
    return YES;
}
@end


2、瀑布流



2.1 创建UICollectionView


控制器 ViewController.m

#import "ViewController.h"
#import "ShopeCellCollectionViewCell.h"
#import "ShopeFlowLayout.h"
#import "Model.h"

@interface ViewController ()<UICollectionViewDataSource>

//用于保存模拟数据
@property(nonatomic,strong) NSMutableArray *dataMutableArray;

@end

static NSString *identifier = @"cell";

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //初始化模拟数据
    _dataMutableArray = [NSMutableArray array];
    
    for (int i =0; i<30; i++) {
        //创建模拟数据模型
        Model *model = [[Model alloc]init];
        //图片的 宽
        model.w = 200;
        //图片的 高
        model.h = (arc4random() % 350) + 50;
        //图片的文字简介
        model.title = @"xx_imag";
        //图片的地址
        model.imgPath=@"老虎";
        //保存到数组中
        [_dataMutableArray addObject:model];
    }
    
    
    //实例化一个流水布局 (自定义布局 )
    ShopeFlowLayout *flowLayout = [[ShopeFlowLayout alloc]init];
    //将数据传递
    flowLayout.dataArray = _dataMutableArray;
    //实例化UICollectionView
    UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:self.view.bounds collectionViewLayout:flowLayout];
    //设置背景
    collectionView.backgroundColor = [UIColor whiteColor];
    //设置数据源代理
    collectionView.dataSource = self;
    //注册Cell  这里通过 xib方式来创建的自定义Cell
    UINib *nibCell = [UINib nibWithNibName:@"ShopeCellCollectionViewCell" bundle:nil];
    
    [collectionView registerNib:nibCell forCellWithReuseIdentifier:identifier];
    
    //添加到控制器上
    [self.view addSubview:collectionView];
}

//组
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
    return 1;
}
//行
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
    return _dataMutableArray.count;
}
//view
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    ShopeCellCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
    cell.backgroundColor=[UIColor whiteColor];
    //设置数据显示
    cell.model = self.dataMutableArray[indexPath.row];
    
    return cell;
}


@end


数据模型 Model.h 

#import <Foundation/Foundation.h>

@interface Model : NSObject

@property (nonatomic,copy) NSString *imgPath;
@property (nonatomic,copy) NSString *title;
@property (nonatomic,assign) NSInteger h;
@property (nonatomic,assign) NSInteger w;


-(instancetype)initWithDic:(NSDictionary *)dic;
+(instancetype)initWithDic:(NSDictionary *)dic;

@end


自定义 Cell 

ShopeCellCollectionViewCell.h

#import <UIKit/UIKit.h>
#import "Model.h"

@interface ShopeCellCollectionViewCell : UICollectionViewCell

//数据模型
@property(nonatomic,copy) Model *model;

@end


ShopeCellCollectionViewCell.m 

#import "ShopeCellCollectionViewCell.h"

@interface ShopeCellCollectionViewCell()
//图片
@property (weak, nonatomic) IBOutlet UIImageView *mImageView;
//对应文字显示
@property (weak, nonatomic) IBOutlet UILabel *mTitleLabel;


@end

@implementation ShopeCellCollectionViewCell

- (void)awakeFromNib {
    [super awakeFromNib];
    
}

-(void)setModel:(Model *)model{
    _model = model;
    _mTitleLabel.text = model.title;
    _mImageView.image = [UIImage imageNamed:model.imgPath];
}

@end

自定义流水布局 

ShopeFlowLayout.h

#import <UIKit/UIKit.h>

@interface ShopeFlowLayout : UICollectionViewFlowLayout

@property(nonatomic,strong) NSArray *dataArray;

@end


ShopeFlowLayout.m

#import "ShopeFlowLayout.h"
#import "Model.h"


@interface ShopeFlowLayout ()
//保存每一列最大的Y值
@property(nonatomic,strong)NSMutableArray *maxYArray;

@end
//列数
static NSInteger maxColumn = 2;

@implementation ShopeFlowLayout

-(instancetype)init{
    
    if (self =[super init]) {
        _maxYArray =[NSMutableArray array];

           }
    
    return self;
}

-(void)prepareLayout{
    [super prepareLayout];

}
//返回每一个cell的属性
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
    //取出collectionViewSize的size
    CGSize collectionViewSize = self.collectionView.frame.size;
    //行间距
    CGFloat columnMargin = 10;
    //列间距
    CGFloat rowMargin = 10;
    //组内间距
    UIEdgeInsets  sectionInsets = UIEdgeInsetsMake(10, 10, 10, 10);
    
    
    //确定cell的宽度
    CGFloat itemWidth = (collectionViewSize.width - sectionInsets.left - sectionInsets.right - (maxColumn-1)*columnMargin)/maxColumn;
    //确定cell的高度
    //得到对应的MODEL数据
    Model *model = _dataArray[indexPath.row];
    //计算高度
    CGFloat itemHeight = itemWidth*model.h/model.w;
    
    //计算cell的 x
    
    CGFloat minMaxY = [self.maxYArray[0] doubleValue];
    //最短的列
    NSInteger minColmn = 0;
    
    for (int i=1; i<_maxYArray.count ; i++) {
        //取出数组中保存的Y值
        CGFloat arryY = [self.maxYArray[i] doubleValue];
        if (minMaxY>arryY) {
            //赋值 Y值
            minMaxY = arryY;
            //赋值最短列
            minColmn = i;
        }
    }
    
    CGFloat itemX = minColmn*itemWidth+minColmn*columnMargin+sectionInsets.left;
    CGFloat itemY = minMaxY +rowMargin;
    
    //获取对应CELL 属性
    UICollectionViewLayoutAttributes *attributes=[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
    //赋值修改
    attributes.frame = CGRectMake(itemX, itemY, itemWidth, itemHeight);
    //记录Y值
    self.maxYArray[minColmn]=@(CGRectGetMaxY(attributes.frame));
    return attributes;
    
}
//返回每一个可见CEll的属性
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
 
    //清空数组
    [self.maxYArray removeAllObjects];
    //初始化数组
    for (int i=0; i<maxColumn; i++) {
        [self.maxYArray addObject:@0];
    }
    
    NSMutableArray *mutableArray = [NSMutableArray array];
    //取出当前所有的Cell的个数
    NSInteger cellCount = [self.collectionView numberOfItemsInSection:0];
    for (int i=0; i<cellCount; i++) {
        //创建每一个Cell对应的indexPath
        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
        //获取对应Cell的属性
        UICollectionViewLayoutAttributes *attributes = [self layoutAttributesForItemAtIndexPath:indexPath];
        
        [mutableArray addObject:attributes];
    }
    return mutableArray;
}

//重新确定滑动范围 
-(CGSize)collectionViewContentSize{
    CGFloat maxY = 0;
    if (self.maxYArray.count>1) {
        for (int i=1; i<maxColumn; i++) {
            CGFloat arryY = [self.maxYArray[i] doubleValue];
            if (arryY>maxY) {
                maxY = arryY;
            }
        }
       
    }
    
    return CGSizeMake(0, maxY+20);
}
@end












早起的年轻人 CSDN认证博客专家 移动开发 项目管理 Java
只要用心去做,每一件事情还是有可能成功的,当然成功是没有界限的,只不过是达到自己心里的那个目标,公众号:我的大前端生涯,一个爱喝茶的程序员,通常会搞搞SpringBoot 、Herbinate、Mybatiys、Android、iOS、Flutter、Vue、小程序等.
©️2020 CSDN 皮肤主题: 代码科技 设计师:Amelia_0503 返回首页