OCiOS开发:集合视图 UICollectionView
来源:互联网 发布:vb中的caption属性 编辑:程序博客网 时间:2024/06/09 13:41
简介
UICollectionView 和 UICollectionViewController 类是iOS6 新引进的API,用于展示集合视图,布局更加灵活,可实现多列布局,用法类似于UITableView 和 UITableViewController 类。
使用UICollectionView 必须实现UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout这三个协议。
UICollectionViewFlowLayout
UICollectionViewFlowLayout是苹果内置的一种流式的布局,其继承于UICollectionViewLayout,负责整个视图的布局,通过这个类,可以高度的定制每个item的位置,以及表头、脚注和装饰视图的位置,只需简单的配置几个属性就可以完成整个布局的搭建。
初始化方法
alloc + init
常用属性
itemSize:设置item尺寸
minimumLineSpacing:设置每行之间的间距
minimumInteritemSpacing:设置每行内部item之间的间距
headerReferenceSize:设置头部size
footerReferenceSize:设置脚注size
scrollDirection:设置滚动方向
sectionHeadersPinToVisibleBounds:设置是否当元素超出屏幕之后固定头部视图位置,默认NO
sectionFootersPinToVisibleBounds:设置是否当元素超出屏幕之后固定尾部视图位置,默认NO
属性配置UICollectionViewFlowLayout是在全局配置布局,想要单独定制每个item元素,需遵守UICollectionViewDelegate以及UICollectionViewDelegateFlowLayout协议,并根据需要实现如下方法即可:
// 1、单独定制item的尺寸- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;// 2、定义每个UICollectionView的margin(间距),对每一个section单独设置边界,即内部cell上下左右距离header和footer的边界(间距)- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;// 3、单独定制每行之间的间距- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;// 4、单独定制每行item之间的间距- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;// 5、单独定制头部视图size- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;// 6、单独定制脚注视图size- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;
UICollectionView
初始化
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;
常用属性
delegate:设置代理
dataSource:设置数据源
allowsSelection:设置是否可以选中
allowsMultipleSelection:设置是否可以多选
注册
- 注册Cell
- (void)registerClass:(Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier;
- 注册头部或尾部视图
// @param elementKind// UICollectionElementKindSectionHeader:头部// UICollectionElementKindSectionFooter:尾部- (void)registerClass:(Class)viewClass forSupplementaryViewOfKind:(NSString *)elementKind withReuseIdentifier:(NSString *)identifier;
重用
// 1、Cell重用- (id)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath*)indexPath;// 2、supplementary View重用- (id)dequeueReusableSupplementaryViewOfKind:(NSString*)elementKind withReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath*)indexPath;
操作
- items操作
// 插入- (void)insertItemsAtIndexPaths:(NSArray *)indexPaths;// 删除- (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths;// 刷新- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths;// 移动- (void)moveItemAtIndexPath:(NSIndexPath *)indexPath toIndexPath:(NSIndexPath *)newIndexPath;
- sections操作
// 插入- (void)insertSections:(NSIndexSet *)sections;// 删除- (void)deleteSections:(NSIndexSet *)sections;// 刷新- (void)reloadSections:(NSIndexSet *)sections;// 移动- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection;
indexPath 获取方法
// 根据某一个点的位置获取item的indexPath- (nullable NSIndexPath *)indexPathForItemAtPoint:(CGPoint)point;// 根据cell获取item的indexPath- (nullable NSIndexPath *)indexPathForCell:(UICollectionViewCell *)cell;
reordering 重新排序
- 一般重新排序步骤需经历如下周期,与手势搭配使用,根据手势的周期变化执行不同的方法:
// 1、设置是否允许移动item- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath;// 2、一般在手势开始时调用,与 indexPathForItemAtPoint 搭配使用,根据手势在视图上的位置获取item所在的indexPath, 开始在特定的索引路径上对cell(单元)进行Interactive Movement(交互式移动工作)- (BOOL)beginInteractiveMovementForItemAtIndexPath:(NSIndexPath *)indexPath;// 3、 在手势作用期间更新交互移动的目标位置。- (void)updateInteractiveMovementTargetPosition:(CGPoint)targetPosition;// 4、在完成手势动作后,结束交互式移动- (void)endInteractiveMovement;// 5、取消移动- (void)cancelInteractiveMovement;// 6、当移动结束后,如下方法将会被触发。- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath*)destinationIndexPath;
UIScrollViewDelegate
// 1、设置是否允许选中- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath;// 2、设置是否允许取消选中- (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath;// 3、选中- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;// 4、取消选中- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;
UICollectionViewDataSource
// 1、设置section组数- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;// 2、设置item个数- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;// 3、配置cell- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;// 4、自定义头部、脚注视图- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath;
tips:配置Cell以及头部或者脚注视图需子类化
UICollectionViewCell
或UICollectionReusableView
,并重写initWithFrame
方法,添加视图;
案例
效果展示
代码示例
自定义 cell 代码示例
#import <UIKit/UIKit.h>@interface CustomCollectionViewCell : UICollectionViewCell@property (nonatomic, strong) UILabel *displayLabel; /**< 展示视图 */@end
#import "CustomCollectionViewCell.h"@implementation CustomCollectionViewCell- (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { self.layer.borderWidth = 1.0f; self.layer.borderColor = [UIColor blackColor].CGColor; self.layer.masksToBounds = YES; [self.contentView addSubview:self.displayLabel]; } return self;}#pragma mark *** Getters ***- (UILabel *)displayLabel { if (!_displayLabel) { _displayLabel = [[UILabel alloc] initWithFrame:self.bounds]; _displayLabel.textAlignment = NSTextAlignmentCenter; } return _displayLabel;}@end
自定义 ReusableView(头部、尾部) 代码示例
#import <UIKit/UIKit.h>// 自定义头部、尾部视图@interface CustomCollectionReusableView : UICollectionReusableView@property (nonatomic, strong) UILabel *displayLabel; /**< 展示标签 */@end
#import "CustomCollectionReusableView.h"@implementation CustomCollectionReusableView- (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self addSubview:self.displayLabel]; } return self;}#pragma mark *** Getters ***- (UILabel *)displayLabel { if (!_displayLabel) { _displayLabel = [[UILabel alloc] initWithFrame:self.bounds]; _displayLabel.backgroundColor = [UIColor redColor]; _displayLabel.textColor = [UIColor whiteColor]; _displayLabel.textAlignment = NSTextAlignmentCenter; } return _displayLabel;}@end
viewController 代码示例
#import <UIKit/UIKit.h>@interface ViewController : UIViewController@end
#import "ViewController.h"#import "CustomCollectionViewCell.h"#import "CustomCollectionReusableView.h"enum NSInteger { InsertItemTag = 100, DeleteItemTag};static NSString *const kTitle = @"CollectionView";static NSString *const kCollectionViewCellIdentifier = @"collectionViewCellIdentifier";static NSString *const kCollectionElementKindSectionHeaderIdentifier = @"headerIdentifier";@interface ViewController () <UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout> { BOOL _selected; NSMutableArray *_dataSource; /**< 数据源 */ NSMutableArray *_selectedDataArr; /**< 选中数据源 */}@property (nonatomic, strong) UICollectionView *collectionView; /**< 集合视图 */@property (nonatomic, strong) UICollectionViewFlowLayout *collectionViewFlowLayout; /**< 流式布局 */- (void)initializeDataSource; /**< 初始化数据源 */- (void)initializeUserInterface; /**< 初始化用户界面 */@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; [self initializeDataSource]; [self initializeUserInterface];}#pragma mark *** Initialize ***- (void)initializeDataSource { _selectedDataArr = [NSMutableArray array]; // 添加数据 _dataSource = [NSMutableArray array]; for (int i = 0; i < 20; i++) { [_dataSource addObject:[NSString stringWithFormat:@"%d", i]]; }}- (void)initializeUserInterface { self.title = kTitle; self.automaticallyAdjustsScrollViewInsets = NO; // 视图加载 [self.view addSubview:self.collectionView]; // 配置导航栏 // 插入 UIBarButtonItem *insertItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(respondsToBarButtonItem:)]; insertItem.tag = InsertItemTag; self.navigationItem.rightBarButtonItem = insertItem; // 删除 UIBarButtonItem *deleteItem = [[UIBarButtonItem alloc] initWithTitle:@"删除" style:UIBarButtonItemStylePlain target:self action:@selector(respondsToBarButtonItem:)]; deleteItem.tag = DeleteItemTag; self.navigationItem.leftBarButtonItem = deleteItem; // 添加长按手势,重排item UILongPressGestureRecognizer *longGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(respondsToGesture:)]; [self.collectionView addGestureRecognizer:longGesture];}#pragma mark *** Gestures ***- (void)respondsToGesture:(UIGestureRecognizer *)gesture { NSLog(@"%@", NSStringFromSelector(_cmd)); // 监听手势状态 switch (gesture.state) { // 1、手势开始 case UIGestureRecognizerStateBegan: { // 获取手势长按位置 NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:[gesture locationInView:self.collectionView]]; // 开始在特定的索引路径上对cell(单元)进行Interactive Movement(交互式移动工作) [self.collectionView beginInteractiveMovementForItemAtIndexPath:indexPath]; } break; // 2、手势变换 case UIGestureRecognizerStateChanged: { // 在手势作用期间更新交互移动的目标位置。 [self.collectionView updateInteractiveMovementTargetPosition:[gesture locationInView:self.collectionView]]; } break; // 3、手势结束 case UIGestureRecognizerStateEnded: { // 在完成手势动作后,结束交互式移动 [self.collectionView endInteractiveMovement]; } break; default: { // 4、默认状态下,取消Interactive Movement。 [self.collectionView cancelInteractiveMovement]; } break; }}#pragma mark *** Events ***- (void)respondsToBarButtonItem:(UIBarButtonItem *)sender { switch (sender.tag) { case InsertItemTag: { // 弹出框 UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"请输入您要添加的数字:" preferredStyle:UIAlertControllerStyleAlert]; [alertController.view layoutIfNeeded]; // 添加文本输入框 [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { textField.clearButtonMode = UITextFieldViewModeWhileEditing; textField.textAlignment = NSTextAlignmentCenter; }]; // 添加按钮 [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:nil]]; [alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { // 获取文本输入框 UITextField *textField = alertController.textFields[0]; // 获取文本 NSString *context = textField.text; // 异常处理 if (context.length == 0) { NSLog(@"请输入文本!"); return ; } // 数据源插入 [_dataSource insertObject:context atIndex:0]; // 单元格插入 [_collectionView insertItemsAtIndexPaths:@[[NSIndexPath indexPathForItem:0 inSection:0]]]; }]]; [self presentViewController:alertController animated:YES completion:nil]; } break; case DeleteItemTag: { if ([self.navigationItem.leftBarButtonItem.title isEqualToString:@"点击删除"]) { NSLog(@"执行删除逻辑!"); // 遍历删除数据源数据 for (NSString *data in _selectedDataArr) { [_dataSource removeObject:data]; } // 刷新集合视图 [self.collectionView reloadData]; self.collectionView.allowsSelection = NO; } // 切换编辑状态 _selected = !_selected; self.navigationItem.leftBarButtonItem.title = _selected ? @"选择删除项" : @"删除"; if ([self.navigationItem.leftBarButtonItem.title isEqualToString:@"选择删除项"]) { self.collectionView.allowsSelection = YES; } } break; default: break; }}#pragma mark *** UICollectionViewDataSource ***// 设置组数- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return 1;}// 设置行数- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return _dataSource.count;}// 设置单元格- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { // item重用机制 CustomCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kCollectionViewCellIdentifier forIndexPath:indexPath]; cell.displayLabel.backgroundColor = [UIColor whiteColor]; cell.displayLabel.text = _dataSource[indexPath.row]; return cell;}// 设置自定义头部、尾部视图- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath { // UICollectionElementKindSectionHeader:头部视图 // UICollectionElementKindSectionFooter:尾部视图 // 如果同时自定义头部、尾部视图,可根据 kind 参数判断当前加载的是头部还是尾部视图,然后进行相应配置。 // 重用机制 CustomCollectionReusableView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:kCollectionElementKindSectionHeaderIdentifier forIndexPath:indexPath]; headerView.displayLabel.text = @"[自定义头部视图]"; return headerView;}// 设置是否允许移动- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath { return YES;}// 移动元素- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { NSLog(@"%@", NSStringFromSelector(_cmd));}#pragma mark *** UICollectionViewDelegateFlowLayout ***// 通过UICollectionViewDelegateFlowLayout提供的方法可高度定制流式布局;- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section { return UIEdgeInsetsMake(0, 10, 0, 10);}#pragma mark *** UICollectionViewDelegate ***// 选中单元格- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { self.navigationItem.leftBarButtonItem.title = @"点击删除"; _selected = YES; CustomCollectionViewCell *cell = (CustomCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath]; cell.displayLabel.backgroundColor = [UIColor greenColor]; [_selectedDataArr addObject:cell.displayLabel.text];}// 取消选中- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath { CustomCollectionViewCell *cell = (CustomCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath]; cell.displayLabel.backgroundColor = [UIColor whiteColor]; [_selectedDataArr removeObject:cell.displayLabel.text];}#pragma mark *** Getters ***- (UICollectionViewFlowLayout *)collectionViewFlowLayout { if (!_collectionViewFlowLayout) { _collectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init]; // 设置item估计值 _collectionViewFlowLayout.estimatedItemSize = CGSizeMake(100, 100); // 全局配置item尺寸,单独定义调用协议方法[sizeForItemAtIndexPath] _collectionViewFlowLayout.itemSize = CGSizeMake(100, 100); // 全局配置每行之间的间距,单独定义可调用协议方法[minimumLineSpacingForSectionAtIndex] _collectionViewFlowLayout.minimumLineSpacing = 10; // 全局配置每行内部item的间距,单独定义可调用协议方法[minimumInteritemSpacingForSectionAtIndex] _collectionViewFlowLayout.minimumInteritemSpacing = 10; // 设置头部size _collectionViewFlowLayout.headerReferenceSize = CGSizeMake(CGRectGetWidth(self.view.bounds), 44); // 设置尾部size _collectionViewFlowLayout.footerReferenceSize = CGSizeZero; // 设置滚动方向 // UICollectionViewScrollDirectionVertical // UICollectionViewScrollDirectionHorizontal _collectionViewFlowLayout.scrollDirection = UICollectionViewScrollDirectionVertical; // 设置是否当元素超出屏幕之后固定头部视图位置,默认NO; _collectionViewFlowLayout.sectionHeadersPinToVisibleBounds = YES; // 设置是否当元素超出屏幕之后固定尾部视图位置,默认NO; _collectionViewFlowLayout.sectionFootersPinToVisibleBounds = YES; } return _collectionViewFlowLayout;}- (UICollectionView *)collectionView { if (!_collectionView) { _collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - 64) collectionViewLayout:self.collectionViewFlowLayout]; _collectionView.backgroundColor = [UIColor brownColor]; // 设置是否允许滚动 _collectionView.scrollEnabled = YES; // 设置是否允许选中,默认YES _collectionView.allowsSelection = NO; // 设置是否允许多选,默认NO _collectionView.allowsMultipleSelection = YES; // 设置代理 _collectionView.delegate = self; // 设置数据源 _collectionView.dataSource = self; // 注册Item [_collectionView registerClass:[CustomCollectionViewCell class] forCellWithReuseIdentifier:kCollectionViewCellIdentifier]; // 注册头部视图 [_collectionView registerClass:[CustomCollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:kCollectionElementKindSectionHeaderIdentifier]; } return _collectionView;}@end
- OCiOS开发:集合视图 UICollectionView
- iOS开发 -- UICollectionView(集合视图)
- iOS开发:集合视图 UICollectionView
- 关于集合视图UICollectionView
- UICollectionView 集合视图
- UICollectionView 集合视图详解
- UICollectionView 集合视图详解
- iOS8 UICollectionView 集合视图
- UICollectionView 集合视图
- 42.集合视图(UICollectionView)
- UICollectionView 集合视图
- 集合视图UICollectionView
- 集合视图 UICollectionView
- 52.集合视图UICollectionView
- UICollectionView-集合视图
- iOS开发-------自定义简单的表情键盘(UICollectionView 集合视图)
- UICollectionView 集合视图 的使用
- iOS编程------集合视图UICollectionView
- CRF++ 条件随机场使用
- Android进程管理详解
- java静态变量,静态方法,静态类
- 提高Linux系统应对短连接的负载能力的方法
- double类型的数据存入电脑失精度
- OCiOS开发:集合视图 UICollectionView
- 权限修饰符
- 一个简单的函数适配器的例子
- 浅谈hibernate的sessionFactory和session
- Hadoop2.5.2 64bit 完全分布式安装
- 自动化测试体系整体解决方案探讨
- python attr相关
- 【Objective-C】面向对象—三大特性
- k近邻matlab图示