iOS常用控件之UICollectionView
2019-06-29 本文已影响0人
平安喜乐698
目录
1. UICollectionView
// 1.创建 布局对象
UICollectionViewFlowLayout *fl=[UICollectionViewFlowLayout new];
// 设置 滚动方向
[fl setScrollDirection:UICollectionViewScrollDirectionVertical];
/*
通常使用dele来设置,而不是通过以下:
// 设置 最小行间距(也可通过dele方法设置)
[fl setMinimumLineSpacing:10];
// 设置 最小项间距(也可通过dele方法设置)
[fl setMinimumInteritemSpacing:10];
// 设置 项大小(也可通过dele方法设置)
[fl setItemSize:CGSizeMake(200, 100)];
// 设置 组内边距(也可通过dele方法设置)
[fl setSectionInset:UIEdgeInsetsZero];
// 垂直滚动时 高起作用(宽无效 为collV宽),水平滚动时 宽起作用(高无效 为collV高)
// 设置 头视图大小(也可通过dele方法设置)
[fl setHeaderReferenceSize:CGSizeMake(100, 100)];
// 设置 尾视图大小(也可通过dele方法设置)
[fl setFooterReferenceSize:CGSizeMake(100, 100)];
*/
// 2.创建 UICollectionView : UIScrollView
UICollectionView *contentCollV=[[UICollectionView alloc]initWithFrame:CGRectZero collectionViewLayout:fl];
// 设置 dele<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
[contentCollV setDelegate:self];
[contentCollV setDataSource:self];
[self.view addSubview:contentCollV];
// 3.注册 cell
[contentCollV registerClass:[] forCellWithReuseIdentifier:NSStringFromClass([])];
[contentCollV registerNib:[UINib nibWithNibName:@"" bundle:nil] forCellWithReuseIdentifier:@""];
// 3.注册 head、foot视图
[contentCollV registerClass:[] forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:NSStringFromClass([])];
[contentCollV registerNib:[UINib nibWithNibName:@"" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@""];
/*
// 删除 指定组
[contentCollV deleteSections:[NSIndexSet indexSetWithIndex:0]];
// 删除 指定项
[contentCollV deleteItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:0]]];
// 插入 指定组
[contentCollV insertSections:[NSIndexSet indexSetWithIndex:0]];
// 插入 指定项
[contentCollV insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:0]]];
// 获取 指定indexPath对应的项
UICollectionViewCell *cell=(UICollectionViewCell *)[contentCollV cellForItemAtIndexPath:indexPath];
*/
自定义CELL MyCell: UICollectionViewCell
-(instancetype)initWithFrame:(CGRect)frame{
self=[super initWithFrame:frame];
if(self){
[self setupUI];
}
return self;
}
自定义头尾视图 :UICollectionReusableView
// 初始化控件
-(void)applyLayoutAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes{
}
需求:更新数据源后立刻设置contentOffset
[self.matchCollectionView reloadData];
[self.matchCollectionView layoutIfNeeded]; // 如果不加,会导致setContentOffset没效果
[self.matchCollectionView setContentOffset:CGPointMake(kScreenWidth, 0)];
dele
<UICollectionViewDelegate,UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>
// 返回 组数
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{return 0;}
// 返回 每组的项数
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{return 0;}
// 返回 每项大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{return CGSizeMake(100, 100);}
// 返回 每项
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"" forIndexPath:indexPath];
return cell;
}
// 返回 每项的最小行间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section{return CGFLOAT_MIN;}
// 返回 每项的最小列间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section{return CGFLOAT_MIN;}
// 返回 组间距
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section{return UIEdgeInsetsZero;}
// 返回 头视图的size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section{return CGSizeMake(100, 100);}
// 返回 尾视图的size
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section{return CGSizeMake(100, 100);}
// 返回 头视图、尾视图
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath{
if([kind isEqualToString:UICollectionElementKindSectionHeader]){
UICollectionReusableView *headV=[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"" forIndexPath:indexPath];
return headV;
}else{
UICollectionReusableView *footV=[collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:@"" forIndexPath:indexPath];
return footV;
}
return [UICollectionReusableView new];
}
// 是否允许选择项
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 选择某项后调用
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{}
// 是否允许反选项
- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 反选某项后调用
- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{}
// 是否 允许项高亮
- (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 项高亮后调用
- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath{}
// 项反高亮后调用
- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath{}
// 是否允许移动项
- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 移动项后调用
- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath{}
// 返回 索引
- (NSArray<NSString *> *)indexTitlesForCollectionView:(UICollectionView *)collectionView{return @[@"A",@"B"];}
// 返回 索引下标
- (NSIndexPath *)collectionView:(UICollectionView *)collectionView indexPathForIndexTitle:(NSString *)title atIndex:(NSInteger)index{}
// 长按时是否显示菜单
- (BOOL)collectionView:(UICollectionView *)collectionView shouldShowMenuForItemAtIndexPath:(NSIndexPath *)indexPath{return true;}
// 是否允许某操作
- (BOOL)collectionView:(UICollectionView *)collectionView canPerformAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{return true;}
// 进行某种操作时调用
- (void)collectionView:(UICollectionView *)collectionView performAction:(SEL)action forItemAtIndexPath:(NSIndexPath *)indexPath withSender:(nullable id)sender{}
// 即将显示项时调用
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{}
// 即将显示头尾视图时调用
- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{}
// 结束显示项时调用
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{}
// 结束显示头尾视图时调用
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath{}
- 流布局
部分代码如下:
1.布局类
YTMyCollectionViewFL.h
#import <UIKit/UIKit.h>
@protocol YTMyCollectionViewFLDele <NSObject>
-(CGFloat)heightWithindexPath:(NSIndexPath *)indexPath;
@end
@interface YTMyCollectionViewFL : UICollectionViewFlowLayout
@property (nonatomic,weak) id<YTMyCollectionViewFLDele> dele;
@end
YTMyCollectionViewFL.m
#import "YTMyCollectionViewFL.h"
#import "YTMyCollectionViewFL.h"
#import "YTMyCollVFLTool.h"
@interface YTMyCollectionViewFL()
@property (nonatomic,assign) CGFloat columnMargin; // 行间距
@property (nonatomic,assign) CGFloat rowMargin; // 列间距
@property (nonatomic,assign) CGFloat columnNum; // 列数
@property (nonatomic,assign) CGFloat width;
@property (nonatomic,assign) UIEdgeInsets sectionInsets;
@property (nonatomic,strong) NSMutableDictionary *maxYDic; // 存储每列maxY
@property (nonatomic,strong) NSMutableArray *attributeArr; // 存储所有att布局属性
@end
@implementation YTMyCollectionViewFL
// collV不用遵循flowlayoutDele,不用实现sizefor/sectionInset
-(instancetype)init{
//
self=[super init];
if(self){
YTMyCollVFLTool *tool=[YTMyCollVFLTool sharedTool];
//
_columnNum=tool.columnNum;
_columnMargin=tool.columnMargin;
_rowMargin=tool.rowMargin;
_sectionInsets=tool.sectionInsets;
}
return self;
}
// 布局前调用
-(void)prepareLayout{
[super prepareLayout];
// 初始化maxYDic
for(int i=0;i<_columnNum;i++){
NSString *column=[NSString stringWithFormat:@"%d",i];
self.maxYDic[column]=@(_sectionInsets.top);
}
// 初始化attArr
[self.attributeArr removeAllObjects];
NSInteger count=[self.collectionView numberOfItemsInSection:0];
for(int i=0;i<count;i++){
UICollectionViewLayoutAttributes *att=[self layoutAttributesForItemAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
[self.attributeArr addObject:att];
}
}
// 返回 总size
-(CGSize)collectionViewContentSize{
//
__block NSString *maxColumn=@"0";
[_maxYDic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
if([_maxYDic[maxColumn] floatValue]<[obj floatValue]){
maxColumn=(NSString *)obj;
}
}];
return CGSizeMake(0, [_maxYDic[maxColumn] floatValue]+_sectionInsets.bottom);
}
// 返回 indexPath对应item的布局属性
-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
// 每列宽
_width=(self.collectionView.frame.size.width-_sectionInsets.left-_sectionInsets.right-_columnMargin*(_columnNum-1))/_columnNum;
// height
CGFloat height=[self.dele heightWithindexPath:indexPath];
// 获取最短列
__block NSString *minColumn=@"0";
[_maxYDic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
if([obj floatValue]<[_maxYDic[minColumn] floatValue]){
minColumn=(NSString *)key;
}
}];
// (x,y)
CGFloat x=_sectionInsets.left+(_columnMargin+_width)*[minColumn floatValue];
CGFloat y=[_maxYDic[minColumn]floatValue]+_rowMargin;
// update maxYDic
_maxYDic[minColumn]=@(y+height);
//
UICollectionViewLayoutAttributes *att=[UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
att.frame=CGRectMake(x, y, _width, height);
return att;
}
// 返回 rect对应的布局属性
-(NSArray<UICollectionViewLayoutAttributes *> *)layoutAttributesForElementsInRect:(CGRect)rect{
return self.attributeArr;
}
-(NSMutableArray *)attributeArr{
if(!_attributeArr){
_attributeArr=[NSMutableArray arrayWithCapacity:10];
}
return _attributeArr;
}
-(NSMutableDictionary *)maxYDic{
if(!_maxYDic){
_maxYDic=[NSMutableDictionary new];
}
return _maxYDic;
}
@end
2.工具类
YTMyCollVFLTool.h
@interface YTMyCollVFLTool : NSObject
@property (nonatomic,assign) CGFloat columnMargin; // 行间距
@property (nonatomic,assign) CGFloat rowMargin; // 列间距
@property (nonatomic,assign) CGFloat columnNum; // 列数
@property (nonatomic,assign) UIEdgeInsets sectionInsets; //
+(instancetype)sharedTool;
@end
YTMyCollVFLTool.m
#import "YTMyCollVFLTool.h"
@implementation YTMyCollVFLTool
static YTMyCollVFLTool *sharedTool;
+(instancetype)sharedTool{
@synchronized (self) {
if(!sharedTool){
sharedTool=[YTMyCollVFLTool new];
}
}
return sharedTool;
}
-(instancetype)init{
self=[super init];
if(self){
//
_columnNum=2;
_columnMargin=10;
_rowMargin=10;
_sectionInsets=UIEdgeInsetsMake(10, 15, 10, 15);
}
return self;
}
@end
3.使用
//
YTMyCollectionViewFL *fl=[YTMyCollectionViewFL new];
fl.dele=self;
fl.scrollDirection=UICollectionViewScrollDirectionVertical;
//
UICollectionView *contentCollV=[[UICollectionView alloc]initWithFrame:CGRectZero collectionViewLayout:fl];
_guideCollV=contentCollV;
[contentCollV setTag:303];
[contentCollV setBackgroundColor:[UIColor whiteColor]];
contentCollV.delegate=self;
contentCollV.dataSource=self;
[self addSubview:contentCollV];
[contentCollV autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero];
[contentCollV registerClass:[YTRecomGuideCollectionViewCell class] forCellWithReuseIdentifier:NSStringFromClass([YTRecomGuideCollectionViewCell class])];
-(CGFloat)heightWithindexPath:(NSIndexPath *)indexPath{
return [_dele heightWithindexPath:indexPath withCollV:_guideCollV];
}