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












  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
iOS-RATreeView是一个开源的第三方库,提供了多层级的UITableView展示功能。使用该库可以轻松实现多级列表的展开与收起。 首先,在项目中引入iOS-RATreeView库。可以使用CocoaPods引入,也可以手动下载并导入。 接下来,在需要使用多级列表的UIViewController中,创建一个RADataObject类型的数组,用来存储数据。RADataObject是iOS-RATreeView中的一个数据模型,用来表示一条记录。每个RADataObject可以包含多个子RADataObject,从而形成多级列表。 ``` // 创建RADataObject数组 NSMutableArray *data = [NSMutableArray array]; // 创建一级列表 RADataObject *level1_1 = [RADataObject dataObjectWithName:@"Level 1-1" children:nil]; RADataObject *level1_2 = [RADataObject dataObjectWithName:@"Level 1-2" children:nil]; RADataObject *level1_3 = [RADataObject dataObjectWithName:@"Level 1-3" children:nil]; // 创建级列表 RADataObject *level2_1 = [RADataObject dataObjectWithName:@"Level 2-1" children:nil]; RADataObject *level2_2 = [RADataObject dataObjectWithName:@"Level 2-2" children:nil]; RADataObject *level2_3 = [RADataObject dataObjectWithName:@"Level 2-3" children:nil]; // 将级列表添加到一级列表中 level1_1.children = @[level2_1, level2_2]; level1_2.children = @[level2_3]; // 将一级列表添加到RADataObject数组中 [data addObject:level1_1]; [data addObject:level1_2]; [data addObject:level1_3]; ``` 创建完数据源后,需要创建RATreeView对象,并设置代理和数据源。 ``` // 创建RATreeView对象 self.treeView = [[RATreeView alloc] initWithFrame:self.view.bounds]; // 设置代理和数据源 self.treeView.delegate = self; self.treeView.dataSource = self; ``` 接下来实现RATreeViewDataSource协议中的方法,用来返回列表的数据。具体实现可以参考下面的代码。 ``` - (UITableViewCell *)treeView:(RATreeView *)treeView cellForItem:(id)item { static NSString *identifier = @"Cell"; UITableViewCell *cell = [treeView dequeueReusableCellWithIdentifier:identifier]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier]; } // 获取RADataObject对象 RADataObject *dataObject = item; // 设置cell的文本 cell.textLabel.text = dataObject.name; return cell; } - (NSInteger)treeView:(RATreeView *)treeView numberOfChildrenOfItem:(id)item { if (item == nil) { // 如果item为nil,表示请求根节点的子节点数量 return self.data.count; } else { // 获取RADataObject对象 RADataObject *dataObject = item; // 返回子节点数量 return dataObject.children.count; } } - (id)treeView:(RATreeView *)treeView child:(NSInteger)index ofItem:(id)item { if (item == nil) { // 如果item为nil,表示请求根节点的子节点 return self.data[index]; } else { // 获取RADataObject对象 RADataObject *dataObject = item; // 返回子节点 return dataObject.children[index]; } } - (BOOL)treeView:(RATreeView *)treeView canEditRowForItem:(id)item { // 返回是否可以编辑 return YES; } - (void)treeView:(RATreeView *)treeView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowForItem:(id)item { if (editingStyle == UITableViewCellEditingStyleDelete) { // 删除节点 RADataObject *parentObject = [treeView parentForItem:item]; if (parentObject) { NSMutableArray *children = [NSMutableArray arrayWithArray:parentObject.children]; [children removeObject:item]; parentObject.children = children; } else { NSMutableArray *data = [NSMutableArray arrayWithArray:self.data]; [data removeObject:item]; self.data = data; } // 刷新列表 [treeView reloadData]; } } ``` 最后,在RATreeViewDelegate协议中实现展开与收起节点的方法。 ``` - (void)treeView:(RATreeView *)treeView willExpandRowForItem:(id)item { // 获取RADataObject对象 RADataObject *dataObject = item; // 设置节点的展开状态 dataObject.expanded = YES; } - (void)treeView:(RATreeView *)treeView willCollapseRowForItem:(id)item { // 获取RADataObject对象 RADataObject *dataObject = item; // 设置节点的展开状态 dataObject.expanded = NO; } ``` 至此,多级列表展开与收起的功能就实现了。在需要展示多级列表的地方,只需要将创建的RATreeView添加到视图中即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

早起的年轻人

创作源于分享

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值