UICollectView 简介(代理,数据源)

本文介绍了iOS中UICollectionView的使用,包括它与UITableView的相似性、必须实现的UICollectionViewDataSource、UICollectionViewDelegate、UICollectionViewDelegateFlowLayout协议。内容涵盖UICollectView的组件、UICollectionViewLayout的重要性,特别是UICollectionViewFlowLayout的流式布局特性,以及预数据源方法prefetchDataSource的学习建议。同时强调了在使用UICollectionView时注册cell的必要性以及UICollectionViewDelegate和UICollectionViewDataSource的关键方法。

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

UICollectionView 和 UICollectionViewController 类是iOS6 新引进的API,用于展示集合视图,布局更加灵活,可实现多列布局,用法类似于UITableView 和 UITableViewController 类。
使用UICollectView必须实现UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout三个协议。

UICollectView的组成部分:跟UITableView一样,UICollectView有自己的Cell。有自己的头部视图,尾部视图(Supplementary Views)相当于UITableView的页脚和页眉。有一个用于修饰整个UICollecView的Decoration Views。
这里写图片描述

在使用UICollectView的时候必须注意的是UICollectViewLayout这个属性。该属性是UICollectView的布局属性。UICollectView跟UICollectViewLayout的关系就跟人的思想跟行为一样。思想控制一个人的行为,在这里UICollectLayout负责界定每一个cell的大小,位置等信息,UICollectView值负责每一个Cell的显示。

UICollectionViewFlowLayout(流式布局)的使用

UICollectViewLayout的子类。称线性布局或者流式布局。

其主要属性有:重点内容

//行间距
@property (nonatomic) CGFloat minimumLineSpacing;
//列间距
@property (nonatomic) CGFloat minimumInteritemSpacing;
//cell的尺寸
@property (nonatomic) CGSize itemSize;
//cell的预计尺寸
@property (nonatomic) CGSize estimatedItemSize;
//滚动的方向
@property (nonatomic) UICollectionViewScrollDirection scrollDirection;
//head的预计尺寸
@property (nonatomic) CGSize headerReferenceSize;
//footer的预计尺寸
@property (nonatomic) CGSize footerReferenceSize;
//UIdgeInsets属性
@property (nonatomic) UIEdgeInsets sectionInset;

例如:

-(void)setflowLayout
{

    CGFloat itemW = 40;
    CGFloat itemH = itemW * 0.8;
    CGFloat itemlineMar = 5;
    CGFloat itemInterMar = itemlineMar;

    UICollectionViewFlowLayout * flowLayout = [[UICollectionViewFlowLayout alloc]init];

    flowLayout.itemSize = CGSizeMake(itemW, itemH);
//    flowLayout.estimatedItemSize = CGSizeMake(40, 30);

    flowLayout.minimumLineSpacing = itemlineMar;
    flowLayout.minimumInteritemSpacing = itemInterMar;

    flowLayout.footerReferenceSize = CGSizeMake(SCREEMW, 30);
    flowLayout.headerReferenceSize = CGSizeMake(SCREEMW, 30);

    flowLayout.sectionInset = UIEdgeInsetsMake(0, 0, 0, 0);

    flowLayout.scrollDirection = UICollectionViewScrollDirectionVertical||
    UICollectionViewScrollDirectionHorizontal;

    flowLayout.sectionHeadersPinToVisibleBounds = YES;
    flowLayout.sectionFootersPinToVisibleBounds = YES;

    self.flowLayout = flowLayout;
}

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
UIcolllectVFlowLayout常用方法:


/**
 根据indexpath设置cell的尺寸

 @param collectionView 哪个UICollectView
 @param collectionViewLayout 哪个布局
 @param indexPath 哪个indexpath
 @return 返回的尺寸
 */
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
    return CGSizeMake(90, 100);
}

/**
 根据section返回UIEdgeInsets

 @param collectionView 哪个UICollectView
 @param collectionViewLayout 哪个布局
 @param section 哪个section
 @return 返回的UIEdgeInsets
 */
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
    return UIEdgeInsetsMake(0,0,0,0);
}

/**
 根据section返回minimumInteritemSpacing值

 @param collectionView 哪个UICollectView
 @param collectionViewLayout 哪个布局
 @param section 哪个section
 @return 返回的minimumInteritemSpacing值
 */
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section{
    return 5.0;
}


/**
 根据section返回minimumInteritemSpacing值

 @param collectionView 哪个UICollectView
 @param collectionViewLayout 哪个布局
 @param section 哪个section
 @return 返回的minimumInteritemSpacing值
 */
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{
    return 10.0;
}

/**
 根据section返回大概的headSize值

 @param collectionView 哪个UICollectView
 @param collectionViewLayout 哪个布局
 @param section 哪个section
 @return 返回的headSize值
 */
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section{
    return CGSizeMake(SCREEMW, 40);
}

/**
  根据section放回大概的footerSize值

 @param collectionView 哪个UICollectView
 @param collectionViewLayout 哪个布局
 @param section 哪个section
 @return 返回的footerSize值
 */
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section{
    return CGSizeMake(SCREEMW, 40);
}

以上方法不一定要实现,根据需要选择需要的api即可。

UICollectionViewDelegate的使用
与UITabelView类似,UICollectView有自己的代理与数据源(UICollectionViewDataSource)方法。

**UICollectView常见属性:*

//布局属性
@property (nonatomic, strong) UICollectionViewLayout *collectionViewLayout;
//代理
@property (nonatomic, weak, nullable) id <UICollectionViewDelegate> delegate;
//数据源
@property (nonatomic, weak, nullable) id <UICollectionViewDataSource> dataSource;

//设置是否允许选中 默认yes
@property (nonatomic) BOOL allowsSelection;

//设置是否允许多选 默认no
@property (nonatomic) BOOL allowsMultipleSelection;

若需要深究UICollectView属性,建议学习一下它的prefetchDataSource(预数据源方法)

UICollectionView的常见方法:

⚠️:在完成UICollection的代理事件之前一定要实现一下一个注册cell的函数,不然会崩溃。


//设置选中某一item,并使视图滑动到相应位置,scrollPosition是滑动位置的相关参数,如下:
/*
typedef NS_OPTIONS(NSUInteger, UICollectionViewScrollPosition) {
    //无
    UICollectionViewScrollPositionNone                 = 0,
    //垂直布局时使用的 对应上中下
    UICollectionViewScrollPositionTop                  = 1 << 0,
    UICollectionViewScrollPositionCenteredVertically   = 1 << 1,
    UICollectionViewScrollPositionBottom               = 1 << 2,
    //水平布局时使用的  对应左中右
    UICollectionViewScrollPositionLeft                 = 1 << 3,
    UICollectionViewScrollPositionCenteredHorizontally = 1 << 4,
    UICollectionViewScrollPositionRight                = 1 << 5
};
*/
- (void)selectItemAtIndexPath:(nullable NSIndexPath *)indexPath animated:(BOOL)animated scrollPosition:(UICollectionViewScrollPosition)scrollPosition;

//将某一item取消选中
- (void)deselectItemAtIndexPath:(NSIndexPath *)indexPath animated:(BOOL)animated;

//重新加载数据
- (void)reloadData;

//下面这两个方法,可以重新设置collection的布局,后面的方法多了一个布局完成后的回调,iOS7后可以用
//使用这两个方法可以产生非常炫酷的动画效果
- (void)setCollectionViewLayout:(UICollectionViewLayout *)layout animated:(BOOL)animated;
- (void)setCollectionViewLayout:(UICollectionViewLayout *)layout animated:(BOOL)animated completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);

//下面这些方法更加强大,我们可以对布局更改后的动画进行设置
//这个方法传入一个布局策略layout,系统会开始进行布局渲染,返回一个UICollectionViewTransitionLayout对象
//这个UICollectionViewTransitionLayout对象管理动画的相关属性,我们可以进行设置
- (UICollectionViewTransitionLayout *)startInteractiveTransitionToCollectionViewLayout:(UICollectionViewLayout *)layout completion:(nullable UICollectionViewLayoutInteractiveTransitionCompletion)completion NS_AVAILABLE_IOS(7_0);
//准备好动画设置后,我们需要调用下面的方法进行布局动画的展示,之后会调用上面方法的block回调
- (void)finishInteractiveTransition NS_AVAILABLE_IOS(7_0);
//调用这个方法取消上面的布局动画设置,之后也会进行上面方法的block回调
- (void)cancelInteractiveTransition NS_AVAILABLE_IOS(7_0);

//获取分区数
- (NSInteger)numberOfSections;

//获取某一分区的item数
- (NSInteger)numberOfItemsInSection:(NSInteger)section;

//下面两个方法获取item或者头尾视图的layout属性,这个UICollectionViewLayoutAttributes对象
//存放着布局的相关数据,可以用来做完全自定义布局,后面博客会介绍
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;
- (nullable UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;

//获取某一点所在的indexpath位置
- (nullable NSIndexPath *)indexPathForItemAtPoint:(CGPoint)point;

//获取某个cell所在的indexPath
- (nullable NSIndexPath *)indexPathForCell:(UICollectionViewCell *)cell;

//根据indexPath获取cell
- (nullable UICollectionViewCell *)cellForItemAtIndexPath:(NSIndexPath *)indexPath;

//获取所有可见cell的数组
- (NSArray<__kindof UICollectionViewCell *> *)visibleCells;

//获取所有可见cell的位置数组
- (NSArray<NSIndexPath *> *)indexPathsForVisibleItems;

//下面三个方法是iOS9中新添加的方法,用于获取头尾视图
- (UICollectionReusableView *)supplementaryViewForElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0);
- (NSArray<UICollectionReusableView *> *)visibleSupplementaryViewsOfKind:(NSString *)elementKind NS_AVAILABLE_IOS(9_0);
- (NSArray<NSIndexPath *> *)indexPathsForVisibleSupplementaryElementsOfKind:(NSString *)elementKind NS_AVAILABLE_IOS(9_0);

//使视图滑动到某一位置,可以带动画效果
- (void)scrollToItemAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UICollectionViewScrollPosition)scrollPosition animated:(BOOL)animated;

//下面这些方法用于动态添加,删除,移动某些分区获取items
- (void)insertSections:(NSIndexSet *)sections;
- (void)deleteSections:(NSIndexSet *)sections;
- (void)reloadSections:(NSIndexSet *)sections;
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection;

- (void)insertItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
- (void)deleteItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
- (void)reloadItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath;

/**
 UICollectView注册一个定义好的cell(拿出来单独写的目的是将注册函数独立出来)
// If a class is registered, it will be instantiated via alloc/initWithFrame:
 @param cellClass 哪个class
 @param identifier 重用标识
 */
- (void)registerClass:(nullable Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier{
    [self.collectView registerClass:cellClass forCellWithReuseIdentifier:identifier];
}

/**
 UICollectView注册一个定义好的cell(拿出来单独写的目的是将注册函数独立出来)
 // If a nib is registered, it must contain exactly 1 top level object which is a UICollectionViewCell.
 @param nib 哪个nib文件
 @param identifier 重用标识
 */
- (void)registerNib:(nullable UINib *)nib forCellWithReuseIdentifier:(NSString *)identifier
{
    [self registerNib:nib forCellWithReuseIdentifier:identifier];
}

/**
 Class注册SupplementaryView

 @param viewClass class
 @param elementKind <#elementKind description#>
 @param identifier <#identifier description#>
 */
- (void)registerClass:(nullable Class)viewClass forSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier{

}

/**
  NIB注册SupplementaryView

 @param nib NIB
 @param kind <#kind description#>
 @param identifier <#identifier description#>
 */
- (void)registerNib:(nullable UINib *)nib forSupplementaryViewOfKind:(NSString *)kind withReuseIdentifier:(NSString *)identifier{

}

/**
 跟UITableView的cell重用机制一样
 @param identifier <#identifier description#>
 @param indexPath <#indexPath description#>
 @return <#return value description#>
 */
- (__kindof UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath{

}

/**
 重用SupplementaryView

 @param elementKind <#elementKind description#>
 @param identifier <#identifier description#>
 @param indexPath <#indexPath description#>
 @return <#return value description#>
 */
- (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath{

}

例如:重点内容

//注册Cell,必须要有
    [self registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"UICollectionViewCell"];

UICollectionViewDelegate的常用方法:
其中的需要事项的方法与UITableViewdelegate中的基本一样:

/**
  是否允许cell被选择的时候高亮

 @param collectionView 哪个UICollectionView
 @param indexPath 哪个indexPath
 @return YES OR NO
 */
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath{}

/**
 cell已经高亮做什么

 @param collectionView 哪个UICollectView
 @param indexPath 哪个indexPath
 */
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath{}


/**
 失去高亮做什么

 @param collectionView 哪个UICollecView
 @param indexPath 哪个indexpath
 */
- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath{}


/**
 cell是否能被选择默认允许

 @param collectionView 哪个UICollectView
 @param indexPath 哪个indexpath
 @return YES OR NO
 */
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath{}

/**
 是否允许失去选择默认允许

 @param collectionView 哪个UICollectView
 @param indexPath 哪个indexpath
 @return YES or NO
 */
- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath{}


// called when the user taps on an already-selected item in multi-select mode

/**
 当cell被选择的时候调用

 @param collectionView 哪个UICollectView
 @param indexPath 哪个indexpath
 */
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{}

/**
 失去选择的时候做什么

 @param collectionView 哪个UICollectView
 @param indexPath 哪个indexpath
 */
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{}


/**
 cell即将被显示出来的时候调用

 @param collectionView 哪个UICollectView
 @param cell 哪个Cell
 @param indexPath 哪个indexpath
 */
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{}



/**
 cell完成显示的时候调用

 @param collectionView 哪个UICollectView
 @param cell 哪个cell
 @param indexPath 哪个indexPath
 */
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{}

/**
 SupplementaryView即将被显示的时候调用

 @param collectionView 哪个UICollectView
 @param view 哪个SupplementaryView
 @param elementKind 哪个元素
 @param indexPath 哪个indexpath
 */
- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{}



/**
 SupplementaryView完成显示的时候调用

 @param collectionView 哪个UICollectView
 @param view 哪个SupplementaryView
 @param elementKind 哪个元素
 @param indexPath 哪个indexpath
 */
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{}


/**
 是否显示编辑菜单(如复制,粘贴等)

 @param collectionView 哪个UICollectView
 @param indexPath 哪个indexpath
 @return YES or NO
 */
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath{}


/**
 菜单中哪些编辑操作可以显示

 @param collectionView 哪个UICollectView
 @param action 哪个编辑行为
 @param indexPath 哪个indexpath
 @param sender 哪个发送者
 @return YES or NO
 */
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{
     NSLog(@"%@",NSStringFromSelector(action));
    if (action == @selector(copy:)){
        return YES;   //此处只显示copy
    }
    return NO;
}


/**
 //对于显示的编辑操作怎么执行

 @param collectionView 哪个UICollectView
 @param action 哪个行为
 @param indexPath 哪个indexpath
 @param sender 哪个发送者
 */
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{

    if (action == @selector(copy:)){
        MyUICollectionViewCell *cell = (MyUICollectionViewCell )[collectionView  cellForItemAtIndexPath:indexPath];
        [[UIPasteboard generalPasteboard] setImage:cell.Icon.ima.image];    //剪贴板存储
    }

}

UICollectionViewDataSource常用方法重点内容

/**
 设置section的rows

 @param collectionView 哪个UICollecView
 @param section 哪个section
 @return 返回的rows
 */
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{}


/**
 设置cell的neirong

 @param collectionView 哪个UICollectView
 @param indexPath 哪个indexPath
 @return 返回的cell
 */
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;



/**
 设置sections数量

 @param collectionView 哪个UICollecView
 @return 返回的sectiins
 */
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;




/**
 设置SupplementaryView

 // The view that is returned must be retrieved from a call to -dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:

 @param collectionView 哪个UICollectView
 @param kind 哪个元素
 @param indexPath 哪个indexpath
 @return 返回的SupplementaryView
 */
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;


/**
 cell是否能勾移动

 @param collectionView 哪个UICollectView
 @param indexPath 哪个indexpath
 @return YES or NO
 */
- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(9_0);

/**
 cell移动的时候调用
在此操作数据
 @param collectionView 哪个UICollectView
 @param sourceIndexPath 开始indexpath
 @param destinationIndexPath 目标indexpath
 */
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath NS_AVAILABLE_IOS(9_0);里写代码片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值