iOS学习笔记33-UICollectionView入门

一、UICollectionView介绍

UICollectionViewUICollectionViewController类是iOS6新引进的API,用于展示集合视图,布局更加灵活,可实现多列布局,用法类似于UITableViewUITableViewController类,但也有所不同。

UICollectionView可以实现如下效果,也是一个常用的控件:

二、UICollectiomView使用

UICollectionView的创建和UITableView的创建有所不同:

1. UITableView的创建只需要设置frame即可使用

UICollectionView除了需要frame,还需要一个布局参数

-(id)initWithFrame:(CGRect)frame /* 尺寸 */
        collectionViewLayout:(UICollectionViewLayout *)layout;/* 布局参数 */
  1. UITableView可以不需要注册Cell视图类,手动创建Cell视图类

    UICollectionView必须注册视图类,才能显示,不需要手动创建

UICollectionView的布局参数:
  1. 是一个UICollectionViewLayout类的对象,

    但我们一般使用它的子类UICollectionViewFlowLayout

  2. 设置布局对象的滚动方向属性scrollDirection
typedef NS_ENUM(NSInteger, UICollectionViewScrollDirection) {
        UICollectionViewScrollDirectionVertical,  /*垂直滚动*/
        UICollectionViewScrollDirectionHorizontal /* 水平滚动 */
};
  1. 垂直滚动,表示Cell方块布局是从左往右,从上到下排列的布局
  2. 水平滚动,表示Cell方块布局是从上往下,从左到右排列的布局
  3. UITableView不同,UICollectionView只能在这里设置顶部视图和底部视图的大小
  4. 设置为垂直滚动时,顶部和底部视图的宽度为UICollectionView的宽度,无法设置
  5. 设置为水平滚动时,顶部和底部视图的高度为UICollectionView的高度,无法设置
UICollectionView的常用对象方法
/* 向容器视图注册Cell方块视图,有2种方式,一种是类名注册,一种是Xib注册 */
- (void)registerClass:(Class)cellClass /* 视图类 */
        forCellWithReuseIdentifier:(NSString *)identifier;/* 绑定标识 */
- (void)registerNib:(UINib *)nib /* Xib */
        forCellWithReuseIdentifier:(NSString *)identifier;/* 绑定标识 */

/* 从缓存池中取出Cell方块视图对象,如果缓存池没有,自动调用alloc/initWithFrame创建 */
- (UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier
                          forIndexPath:(NSIndexPath *)indexPath;

/* kind参数设置 */
NSString *const UICollectionElementKindSectionHeader;/* 顶部视图用这个 */
NSString *const UICollectionElementKindSectionFooter;/* 底部视图用这个 */
/* 向容器视图注册顶部视图或者底部视图,有2种方式,一种是类名注册,一种是Xib注册 */
- (void)registerClass:(Class)viewClass
        forSupplementaryViewOfKind:(NSString *)kind /* 参考上面 */
               withReuseIdentifier:(NSString *)identifier;/* 绑定标识 */
- (void)registerNib:(UINib *)nib
        forSupplementaryViewOfKind:(NSString *)kind /* 参考上面 */
               withReuseIdentifier:(NSString *)identifier;/* 绑定标识 */

/* 从缓存池中取出顶部视图对象或者底部视图对象,如果缓存池没有,自动调用alloc/initWithFrame创建 */
- (UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)kind
                              withReuseIdentifier:(NSString *)identifier
                                     forIndexPath:(NSIndexPath *)indexPath;

UICollectionView的数据源方法
@required
/* 设置容器视图各个组都有多少个Cell方块 */
- (NSInteger)collectionView:(UICollectionView *)collectionView
     numberOfItemsInSection:(NSInteger)section;
/* 设置Cell方块视图,类似于UITableViewCell的设置 */
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
                  cellForItemAtIndexPath:(NSIndexPath *)indexPath;
@optional
/* 容器视图有多少个组,默认返回1 */
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView;
/* 设置顶部视图和底部视图,通过kind参数分辨是设置顶部还是底部 */
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
           viewForSupplementaryElementOfKind:(NSString *)kind
                                 atIndexPath:(NSIndexPath *)indexPath;
UICollectionViewDelegate的常用方法
/* 选中Cell方块时调用 */
- (void)collectionView:(UICollectionView *)collectionView
        didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
/* 取消选中Cell方块时调用 */
- (void)collectionView:(UICollectionView *)collectionView
        didDeselectItemAtIndexPath:(NSIndexPath *)indexPath;

我们使用更多的是UICollectionViewDelegate子协议UICollectionViewDelegateFlowLayout

该协议不仅包含父协议所有方法,还可以进行一些布局设置

UICollectionViewDelegateFlowLayout的常用布局方法
/* 设置每个方块的尺寸大小 */
- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout*)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
/* 设置方块视图和边界的上下左右间距 */
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
                        layout:(UICollectionViewLayout*)collectionViewLayout
        insetForSectionAtIndex:(NSInteger)section;

下面是我自定义的Cell视图类、顶部视图类、底部视图类,目录结构如下:

方块视图LTCollectionViewCell.h
#import <UIKit/UIKit.h>
@interface LTCollectionViewCell : UICollectionViewCell
@property (strong, nonatomic) UILabel *textLabel;
/* 方块视图的缓存池标示 */
+ (NSString *)cellIdentifier;
/* 获取方块视图对象 */
+ (instancetype)cellWithCollectionView:(UICollectionView *)collectionView
                          forIndexPath:(NSIndexPath *)indexPath;
@end
方块视图LTCollectionViewCell.m
#import "LTCollectionViewCell.h"
@implementation LTCollectionViewCell
/* 方块视图的缓存池标示 */
+ (NSString *)cellIdentifier{
    static NSString *cellIdentifier = @"CollectionViewCellIdentifier";
    return cellIdentifier;
}
/* 获取方块视图对象 */
+ (instancetype)cellWithCollectionView:(UICollectionView *)collectionView
                          forIndexPath:(NSIndexPath *)indexPath
{
    //从缓存池中寻找方块视图对象,如果没有,该方法自动调用alloc/initWithFrame创建一个新的方块视图返回
    LTCollectionViewCell *cell =
        [collectionView dequeueReusableCellWithReuseIdentifier:[LTCollectionViewCell cellIdentifier]
                                                  forIndexPath:indexPath];
    return cell;
}
/* 注册了方块视图后,当缓存池中没有底部视图的对象时候,自动调用alloc/initWithFrame创建 */
- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        //创建label
        UILabel *textLabel = [[UILabel alloc] init];
        //设置label尺寸
        CGFloat x = 5;
        CGFloat y = 5;
        CGFloat width = frame.size.width - 10;
        CGFloat height = frame.size.height - 10;
        textLabel.frame = CGRectMake(x, y, width, height);
        //设置label属性
        textLabel.numberOfLines = 0;
        textLabel.textAlignment = NSTextAlignmentCenter;
        textLabel.font = [UIFont systemFontOfSize:15];
        //添加到父控件
        [self.contentView addSubview:textLabel];
        self.textLabel = textLabel;
    }
    return self;
}
@end
顶部视图LTCollectionHeaderView.h
#import <UIKit/UIKit.h>
@interface LTCollectionHeaderView : UICollectionReusableView
@property (strong, nonatomic) UILabel *textLabel;
/* 顶部视图的缓存池标示 */
+ (NSString *)headerViewIdentifier;
/* 获取顶部视图对象 */
+ (instancetype)headerViewWithCollectionView:(UICollectionView *)collectionView
                                forIndexPath:(NSIndexPath *)indexPath;
@end
顶部视图LTCollectionHeaderView.m
#import "LTCollectionHeaderView.h"

@implementation LTCollectionHeaderView
/* 顶部视图的缓存池标示 */
+ (NSString *)headerViewIdentifier{
    static NSString *headerIdentifier = @"headerViewIdentifier";
    return headerIdentifier;
}
/* 获取顶部视图对象 */
+ (instancetype)headerViewWithCollectionView:(UICollectionView *)collectionView
                                forIndexPath:(NSIndexPath *)indexPath
{
    //从缓存池中寻找顶部视图对象,如果没有,该方法自动调用alloc/initWithFrame创建一个新的顶部视图返回
    LTCollectionHeaderView *headerView =
        [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader
                                           withReuseIdentifier:[LTCollectionHeaderView headerViewIdentifier]
                                                  forIndexPath:indexPath];
    return headerView;
}
/* 注册了顶部视图后,当缓存池中没有顶部视图的对象时候,自动调用alloc/initWithFrame创建 */
- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        //创建label
        UILabel *textLabel = [[UILabel alloc] init];
        //设置label尺寸
        CGFloat x = 5;
        CGFloat y = 5;
        CGFloat width = frame.size.width - 10;
        CGFloat height = frame.size.height - 10;
        textLabel.frame = CGRectMake(x, y, width, height);
        //设置label属性
        textLabel.numberOfLines = 0;
        textLabel.textAlignment = NSTextAlignmentCenter;
        //添加到父控件
        [self addSubview:textLabel];
        self.textLabel = textLabel;
    }
    return self;
}
@end
底部视图LTCollectionFooterView.h
#import <UIKit/UIKit.h>
@interface LTCollectionFooterView : UICollectionReusableView
@property (strong, nonatomic) UILabel *textLabel;
/* 底部视图的缓存池标示 */
+ (NSString *)footerViewIdentifier;
/* 获取底部视图对象 */
+ (instancetype)footerViewWithCollectionView:(UICollectionView *)collectionView
                                forIndexPath:(NSIndexPath *)indexPath;
@end
底部视图LTCollectionFooterView.m
#import "LTCollectionFooterView.h"

@implementation LTCollectionFooterView
/* 底部视图的缓存池标示 */
+ (NSString *)footerViewIdentifier{
    static NSString *footerIdentifier = @"footerViewIdentifier";
    return footerIdentifier;
}
/* 获取底部视图对象 */
+ (instancetype)footerViewWithCollectionView:(UICollectionView *)collectionView
                                forIndexPath:(NSIndexPath *)indexPath
{
    //从缓存池中寻找底部视图对象,如果没有,该方法自动调用alloc/initWithFrame创建一个新的底部视图返回
    LTCollectionFooterView *footerView =
            [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter
                                               withReuseIdentifier:[LTCollectionFooterView footerViewIdentifier]
                                                      forIndexPath:indexPath];
    return footerView;
}
/* 注册了底部视图后,当缓存池中没有底部视图的对象时候,自动调用alloc/initWithFrame创建 */
- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        //创建label
        UILabel *textLabel = [[UILabel alloc] init];
        //设置label尺寸
        CGFloat x = 5;
        CGFloat y = 5;
        CGFloat width = frame.size.width - 10;
        CGFloat height = frame.size.height - 10;
        textLabel.frame = CGRectMake(x, y, width, height);
        //设置label属性
        textLabel.numberOfLines = 0;
        textLabel.textAlignment = NSTextAlignmentCenter;
        //添加到父控件
        [self addSubview:textLabel];
        self.textLabel = textLabel;
    }
    return self;
}
@end
下面是使用实例:
1. 视图控制器属性和相关方法
#import "ViewController.h"
#import "LTCollectionViewCell.h"
#import "LTCollectionHeaderView.h"
#import "LTCollectionFooterView.h"

@interface ViewController () <UICollectionViewDataSource,
                              UICollectionViewDelegateFlowLayout>
@property (strong, nonatomic) UICollectionView *collectionView;/*< 容器视图 */
@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //初始化容器视图
    [self initCollectionView];
}
2. 初始化容器视图
/* 初始化容器视图 */
- (void)initCollectionView
{
    CGFloat x = 0;
    CGFloat y = 20;
    CGFloat width = self.view.frame.size.width;
    CGFloat height = self.view.frame.size.height - 20;
    //创建布局对象
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    //设置滚动方向为垂直滚动,说明方块是从左上到右下的布局排列方式
    layout.scrollDirection = UICollectionViewScrollDirectionVertical;
    //设置顶部视图和底部视图的大小,当滚动方向为垂直时,设置宽度无效,当滚动方向为水平时,设置高度无效
    layout.headerReferenceSize = CGSizeMake(100, 40);
    layout.footerReferenceSize = CGSizeMake(100, 40);
    //创建容器视图
    CGRect frame = CGRectMake(x, y, width, height);
    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:frame
                                                          collectionViewLayout:layout];
    collectionView.delegate = self;//设置代理
    collectionView.dataSource = self;//设置数据源
    collectionView.backgroundColor = [UIColor whiteColor];//设置背景,默认为黑色
    //添加到主视图
    [self.view addSubview:collectionView];
    self.collectionView = collectionView;

    //注册容器视图中显示的方块视图
    [collectionView registerClass:[LTCollectionViewCell class]
            forCellWithReuseIdentifier:[LTCollectionViewCell cellIdentifier]];
    //注册容器视图中显示的顶部视图
    [collectionView registerClass:[LTCollectionHeaderView class]
       forSupplementaryViewOfKind:UICollectionElementKindSectionHeader
              withReuseIdentifier:[LTCollectionHeaderView headerViewIdentifier]];
    //注册容器视图中显示的底部视图
    [collectionView registerClass:[LTCollectionFooterView class]
       forSupplementaryViewOfKind:UICollectionElementKindSectionFooter
              withReuseIdentifier:[LTCollectionFooterView footerViewIdentifier]];

}
3. UICollectionViewDataSource数据源方法
#pragma mark - UICollectionViewDataSource
/* 设置容器中有多少个组 */
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
    return 10;
}
/* 设置每个组有多少个方块 */
- (NSInteger)collectionView:(UICollectionView *)collectionView
     numberOfItemsInSection:(NSInteger)section
{
    return 20;
}
/* 设置方块的视图 */
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
                  cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    //获取cell视图,内部通过去缓存池中取,如果缓存池中没有,就自动创建一个新的cell
    LTCollectionViewCell *cell =
            [LTCollectionViewCell cellWithCollectionView:collectionView
                                            forIndexPath:indexPath];
    //设置cell属性
    cell.contentView.backgroundColor = [UIColor redColor];
    cell.textLabel.text = [NSString stringWithFormat:@"Cell %2ld",indexPath.row];

    return cell;
}
/* 设置顶部视图和底部视图 */
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
           viewForSupplementaryElementOfKind:(NSString *)kind
                                 atIndexPath:(NSIndexPath *)indexPath
{
    if ( [kind isEqualToString:UICollectionElementKindSectionHeader] ) {//顶部视图
        //获取顶部视图
        LTCollectionHeaderView *headerView =
            [LTCollectionHeaderView headerViewWithCollectionView:collectionView
                                                    forIndexPath:indexPath];
        //设置顶部视图属性
        headerView.backgroundColor = [UIColor orangeColor];
        headerView.textLabel.text = [NSString stringWithFormat:@"-Header-%ld-",indexPath.section];
        return headerView;

    } else if( [kind isEqualToString:UICollectionElementKindSectionFooter] ) {//底部视图
        //获取底部视图
        LTCollectionFooterView *footerView =
             [LTCollectionFooterView footerViewWithCollectionView:collectionView
                                                     forIndexPath:indexPath];
        //设置底部视图属性
        footerView.backgroundColor = [UIColor greenColor];
        footerView.textLabel.text = [NSString stringWithFormat:@"-Footer-%ld-",indexPath.section];
        return footerView;
    }
    return nil;
}
4. UICollectionViewDelegateFlowLayout布局代理方法
#pragma mark - UICollectionViewDelegateFlowLayout
/* 设置各个方块的大小尺寸 */
- (CGSize)collectionView:(UICollectionView *)collectionView
                  layout:(UICollectionViewLayout*)collectionViewLayout
  sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat width = 50;
    CGFloat height = 50;
    return CGSizeMake(width, height);
}
/* 设置每一组的上下左右间距 */
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
                        layout:(UICollectionViewLayout*)collectionViewLayout
        insetForSectionAtIndex:(NSInteger)section
{
    return UIEdgeInsetsMake(10, 10, 10, 10);
}
5. 父协议UICollectionViewDelegate的代理方法
#pragma mark - UICollectionViewDelegate
/* 方块被选中会调用 */
- (void)collectionView:(UICollectionView *)collectionView
        didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"点击选择了第%ld组第%ld个方块",indexPath.section,indexPath.row);
}
/* 方块取消选中会调用 */
- (void)collectionView:(UICollectionView *)collectionView
        didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"取消选择第%ld组第%ld个方块",indexPath.section,indexPath.row);
}
@end
效果图如下,左边为垂直滚动效果,右边为水平滚动效果

如果修改下布局代理方法的上下左右边界距离:
/* 设置每一组的上下左右间距 */
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView
                        layout:(UICollectionViewLayout*)collectionViewLayout
        insetForSectionAtIndex:(NSInteger)section
{
    return UIEdgeInsetsMake(0, 0, 0, 0);
}

上面的代码Demo点这里:LearnDemo里面的CollectionViewDemo

如果有什么问题可以在下方评论区中提出!O(∩_∩)O哈!
时间: 2024-11-01 21:41:44

iOS学习笔记33-UICollectionView入门的相关文章

iOS学习笔记11-多线程入门

一.iOS多线程 iOS多线程开发有三种方式: NSThread NSOperation GCD iOS在每个进程启动后都会创建一个主线程,更新UI要在主线程上,所以也称为UI线程,是其他线程的父线程. 线程和进程的区别傻傻分不清楚: 线程(thread):用于指代独立执行的代码段. 进程(process):用于指代一个正在运行的可执行程序,它可以包含多个线程. 二.NSThread NSThreadhi轻量级的多线程开发,需要自己管理线程生命周期 创建线程主要实现方法: /* 直接将操作添加到

IOS学习笔记-- SQLite的应用

1 // 2 // HMViewController.m 3 // 02-SQLite的应用 4 // 5 // Created by apple on 14-7-24. 6 // Copyright (c) 2014年 heima. All rights reserved. 7 // 8 9 #import "HMViewController.h" 10 #import <sqlite3.h> 11 12 @interface HMViewController () 13

iOS: 学习笔记, 用代码驱动自动布局实例

iOS自动布局是设置iOS界面的利器. 本实例展示了如何使用自动布局语言设置水平布局, 垂直布局 1. 创建空白iOS项目 2. 添加一个控制器类, 修改YYAppDelegate.m文件 #import "YYAppDelegate.h" #import "YYViewController.h" @implementation YYAppDelegate - (BOOL)application:(UIApplication *)application didFin

iOS: 学习笔记, 使用performSelectorOnMainThread及时刷新UIImageView

在iOS中, 界面刷新在主线程中进行, 这导致NSURLSession远程下载图片使用UIImageView直接设置Image并不能及时刷新界面. 下面的代码演示了如何使用 performSelectorOnMainThread: withObject:  waitUntilDone: 方法来及时刷新图片 1. 创建iOS空应用程序(Empty Application). 2. 加入一个控制器类. 在YYAppDelegate.m中修改 #import "MainViewController.h

【Smallfan的ios学习笔记】卷首引

[关于自己] 似乎先要自我介绍一下.首先我是一名三流专科院校的工科男生,所学的专业是计算机信息管理.计算机信息管理这个专业,说实话当时填报也并不了解,就冲着学校专业简介上面写着oracle开发运维而去,结果上天跟我开了个玩笑,这个专业分了两个方向,一个是系统开发与运用(SQL方向),一个是数据库运维与应用(oracle方向),很荣幸就被分到了SQL方向.一进这个专业,第一件事就是查询这三年将会开什么课程,课表如下: 简要筛选一下主要课程就是JAVA编程基础.JSP程序设计.JavaScript.

iOS学习笔记(八)——iOS网络通信http之NSURLConnection

转自:http://blog.csdn.net/xyz_lmn/article/details/8968182 移动互联网时代,网络通信已是手机终端必不可少的功能.我们的应用中也必不可少的使用了网络通信,增强客户端与服务器交互.这一篇提供了使用NSURLConnection实现http通信的方式. NSURLConnection提供了异步请求.同步请求两种通信方式. 1.异步请求 iOS5.0 SDK NSURLConnection类新增的sendAsynchronousRequest:queu

iOS学习笔记---c语言第十一天

函数指针 一.函数指针定义 //函数声明:声明我是一个什么函数 //求两个数的和 //函数的类型:int (int x,int y) //即:我是一个返回值为整型,有两个整型参数的函数. //函数名是 sum int sum(int x,int y); 函数指针定义p是变量,其他是类型(通常没有形参a,b) //函数指针类型 int (*)(int x,int y) //描述:指向 返回值为 int 两个int参数 的 指针类型 //函数指针变量: p //初始值 : sum printf("%

iOS学习笔记之UITableViewController&amp;UITableView

iOS学习笔记之UITableViewController&UITableView 写在前面 上个月末到现在一直都在忙实验室的事情,与导师讨论之后,发现目前在实验室完成的工作还不足以写成毕业论文,因此需要继续思考新的算法.这是一件挺痛苦的事情,特别是在很难找到与自己研究方向相关的文献的时候.也许网格序列水印这个课题本身的研究意义就是有待考证的.尽管如此,还是要努力的思考下去.由于实验室的原因,iOS的学习进度明显受到影响,加之整理文档本身是一件耗费时间和精力的事情,因此才这么久没有写笔记了. M

iOS: 学习笔记, Swift操作符定义

Swift操作符可以自行定义, 只需要加上简单的标志符即可. @infix 中置运算. 如+,-,*,/运算 @prefix 前置运算. 如- @postfix 后置运算. a++, a-- @assignment 赋值运算. +=, -=, --a, ++a // // main.swift // SwiftBasic // // Created by yao_yu on 14-7-27. // Copyright (c) 2014年 yao_yu. All rights reserved.

现代C++学习笔记之二入门篇2,数据转换

static_cast:    这种强制转换只会在编译时检查. 如果编译器检测到您尝试强制转换完全不兼容的类型,则static_cast会返回错误. 您还可以使用它在基类指针和派生类指针之间强制转换,但是,编译器在无法分辨此类转换在运行时是否是安全的. dynamic_cast: dynamic_cast在运行时检查基类指针和派生类指针之间的强制转换. dynamic_cast 是比 static_cast 更安全的强制类型转换,但运行时检查会带来一些开销. const_cast:    con