UITableView 表格视图
一 UITableView
1.1是什么?
以列表的方式展示数据的一种控件,且继承自UISrollView,默认是只能上下滚动;
1.2 使用步骤:
1)创建UITableView对象,并设置样式;
2)配置要展示的数据和外观;
三问:
1)有几个分区?
2)每个分区有多少行?
3)每行的展示的内容是什么?
3)把它添加到父视图上显示;
见【Demo】-【1-UITableView】
-
(void)viewDidLoad {
[super viewDidLoad];self.automaticallyAdjustsScrollViewInsets = NO;(消除导航控制器对其的影响)
/********** 创建UITableView ************/
//UITableViewStylePlain 普通平板样式
//UITableViewStyleGrouped 分组样式
UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, screenBounds.size.width, screenBounds.size.height-64) style:UITableViewStylePlain];myTableView.delegate = self;
myTableView.dataSource = self;[self.view addSubview:myTableView];
}
pragma mark -UITableViewDataSource
//三问 【** 重点 **】
//1问,告诉tableView应该显示多少个分区【如果不实现,默认是1个分区】
-
(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
//2问,告诉tableView每个分区显示多少行 (该方法有几个分区调用几次)
-
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.dataArray count];
}
//3问,告诉tableView每一行显示的具体内容是什么
-
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//创建静态的标识
static NSString *cellID = @"MyCell";
//先从tableView的复用池中去查找没有带cellID标识的单元格;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
//如果没有找到(复用池中没有符合条件的单元格)
if (cell == nil) {
//自己创建一个新的单元格,并初始化单元格的样式,给它加上标识
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];}
//什么是indexPath?indexPath.row?
MyModel *model = self.dataArray[indexPath.row];
cell.textLabel.text = model.title;//返回符合条件的单元格对象;
return cell;
}
1.3 cell简介 【重点】
UITableView的每一行都是一个UITableViewCell类型的对象,通过dataSource的第三问来初始化每一行;
【cell 的复用机制】
当滚动列表时候,部分UITableViewCell会移出窗口;UITableView会将移出去的UITableViewCell放入到一个复用池中,等待重用,当UITableView要求返回UITableViewCell的时候,会先查看复用池,如果池中有未使用的病符合条件的UITableViewCell,就会直接拿来使用,并重新配置这个UITableViewCell展示的内容,然后返回给UITableView,如果池子中没有符合条件的cell,那么则创建一个新的UITableViewCell对象,并返回!
cell的复用机制保证了值创建有限个cell的对象,来显示无限条数据,极大限度的节约了内存的开销,提高了性能,具有极大的借鉴意义;
1.4 UITableView的原理
a 先询问有几个分区
b 根据分区的个数,再多次询问每个分区有多少行,每次询问的时候,会携带分区的section;
c 根据分区号及分区内的行号,再多次询问每一行显示的内容是什么,其中分区号section和行号row会组成一个NSIndexPath的类型,作为参数传递给方法;
-
(void)viewDidLoad {
[super viewDidLoad];//1.请求数据
[self reloadData];
//2.创建UITableView
[self creatUITableView];
}
-(void)creatUITableView
{
self.automaticallyAdjustsScrollViewInsets = NO;//添加背景图片
UIImageView *bgImg = [[UIImageView alloc] initWithFrame:screenBounds];
bgImg.image = [UIImage imageNamed:@"5.jpg"];
// [self.view addSubview:bgImg];UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, screenBounds.size.width, screenBounds.size.height-64) style:UITableViewStyleGrouped];
//必写
myTableView.delegate = self;
myTableView.dataSource = self;
// myTableView.backgroundColor = [UIColor clearColor];
myTableView.backgroundView = bgImg;UIImageView *headerView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 200)];
headerView.image = [UIImage imageNamed:@"10.jpg"];
headerView.contentMode = UIViewContentModeScaleAspectFit;
UIImageView *footerView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 0, 200)];
footerView.image = [UIImage imageNamed:@"15.jpg"];
footerView.contentMode = UIViewContentModeScaleAspectFit;
//给myTableView设置头部视图
myTableView.tableHeaderView = headerView;
//给myTableView设置尾部视图
myTableView.tableFooterView = footerView;[self.view addSubview:myTableView];
}
pragma mark -UITableViewDataSource
//3问 每行显示的内容是什么
-
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = @"cellName";UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
//系统给我们提供了3中Cell样式
// UITableViewCellStyleDefault,
// UITableViewCellStyleValue1,
// UITableViewCellStyleValue2,
// UITableViewCellStyleSubtitle
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
}
//将数据源中的数据,赋值给cell对象展示出来
UserModel *model = self.dataArray[indexPath.section][indexPath.row];
//1.显示主标题
cell.textLabel.text = model.name;
//2.设置头像
cell.imageView.image = [UIImage imageNamed:model.iconImage];//设置圆角
cell.imageView.layer.cornerRadius = 8;
cell.imageView.layer.masksToBounds = YES;
// cell.imageView.layer.borderColor = (__bridge CGColorRef)([UIColor redColor]);
// cell.imageView.layer.borderWidth = 10;//3.显示副标题
cell.detailTextLabel.text = model.detailTitle;//设置cell右侧的提示样式
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.backgroundColor = [UIColor clearColor];return cell;
}
/**************************** 相关属性 *******************************/
//设置分区cell的高度
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 80;
}
//设置分区的头部视图的标题
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [NSString stringWithFormat:@"%c区的头部标题",(char)('A'+section)];
}
//设置分区的尾部标题
-(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
return [NSString stringWithFormat:@"%c区的尾部标题",(char)('A'+section)];
}
/****************** 自定义分区的头部,尾部视图 **********************/
//当同时设置分区的头部标题和头部视图,那么优先显示头部视图
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.text = [NSString stringWithFormat:@"%c区的头部标题",(char)('A'+section)];
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont systemFontOfSize:20];
label.backgroundColor = [UIColor cyanColor];
label.textColor = [UIColor redColor];
return label;
}
-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.text = [NSString stringWithFormat:@"%c区的尾部标题",(char)('A'+section)];
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont systemFontOfSize:15];
label.backgroundColor = [UIColor magentaColor];
label.textColor = [UIColor yellowColor];
return label;
}
/********************* 设置分区的头部视图的高度 ****************/
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 100;
}
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
return 50;
}
//设置右边索引
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
NSMutableArray *mArr = [NSMutableArray array];
for (int i='A'; i<='Z'; i++) {
NSString *str = [NSString stringWithFormat:@"%c",i];
[mArr addObject:str];
}
return mArr;
}
1.5 UITableViewController 表格视图控制器
UIViewController 管理视图的
UINavigationController 管理多个UIViewController
UITabBarController 即可以管理导航控制器,也可以管理UIViewController
2.1 概念
UITableViewController管理的是一个UITableView;
为了配合UITableView的使用而专门设立的一种特殊控制器,专门用来管理表格视图;
2.2 特点:
1)继承自UIViewController
2)自带的视图已经是UITableView类型,通过 .tableView的属性来访问自己携带的表格视图;
3)控制器本身已经默认遵守了UITableViewDelegate和UITableViewDataSource,并且设置了自己作为该表格式图的代理对象;
4)创建一个表格式图控制器类,继承自UITableViewController,在这个类中专心处理相关代理方法【最主要的三问】;
见【Demo】-【3-UITableViewController】
-
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//从表格视图的复用池中按照之前注册指定的标识去取可重用的对象;
//该方法一定会返回一个不为nil的对象;
//因为:复用池中如果没有可重用的单元格,系统会根据之前注册的类,自动的创建一个单元格对象并返回;
//如果复用池中有可重用的单元格,系统会直接返回;
//优点:自动处理一切细节,减少代码量;
//缺点:这种形式返回的cell对象,只能是默认的样式,其他的三种样式无法设置;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell" forIndexPath:indexPath];//取出数据源中对应的数据模型,并展示在cell上
StudentModel *model = self.dataArray[indexPath.section][indexPath.row];
cell.textLabel.text = model.name;
cell.imageView.image = [UIImage imageNamed:model.icon];cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 100;
}
pragma mark -UITableViewDelegate
//一答 【** 重点 **】
//当选中cell的时候,调用该方法
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//拿到当前点击的cell所对应的数据模型
StudentModel *model = self.dataArray[indexPath.section][indexPath.row];
//跳转到详情页面
DeatilViewController *dvc = [[DeatilViewController alloc] initWithNibName:@"DeatilViewController" bundle:nil];
//把这个model属性传值给详情页面
dvc.model = model;
__block MyTableViewController *weakself = self;
dvc.block = ^{
//刷新当前的tableView(系统自带的方法)
[weakself.tableView reloadData];
};
[self.navigationController pushViewController:dvc animated:YES];
}
关于单元格的实现方法:
方式一:
1)定义静态标识
2)根据标识从复用池中取对象
3)如果有,重新赋值后,直接使用
4)如果没有,那么新建一个单元格
方法二:
1)在viewDidLoad中,提前注册号单元格,并指定标识
2)在第三问时,直接从复用池中取,就算没有可重用的单元格,系统内部会根据一早注册号的单元格样式创建单元格,并返回,如果有可重用的,直接返回;
《但方法二生成的单元格样式只能是默认样式,其他样式无法设置》
两种设置cell显示内容的方式: 【** 重点 **】
第一种:
-
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//创建静态的标识
static NSString *cellID = @"MyCell";
//先从tableView的复用池中去查找没有带cellID标识的单元格;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
//如果没有找到(复用池中没有符合条件的单元格)
if (cell == nil) {
//自己创建一个新的单元格,并初始化单元格的样式,给它加上标识
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];}
//什么是indexPath?indexPath.row?
MyModel *model = self.dataArray[indexPath.row];
cell.textLabel.text = model.title;//返回符合条件的单元格对象;
return cell;
}
第二种:
//提前注册cell
[cView registerClass:[MyCell class] forCellWithReuseIdentifier:@"Cell"];
//3问 每一项显示什么内容
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//从复用池中取有没有符合要求的单元格,如果有,直接返回使用,如果没有,系统会根据之前注册的单元格,自动的创建一个单元格对象,并返回;
MyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
//因为UICollectionViewCell是系统自带的cell,所以没有提供样式,没有提供对应的空间,只能设置相关属性;
cell.model = self.dataArray[indexPath.section][indexPath.row];
cell.backgroundColor = [UIColor orangeColor];
return cell;
}
如果cell用xib写的话,提前注册用下面这种写法:
[self.tableView registerNib:[UINib nibWithNibName:@"AppCell" bundle:nil] forCellReuseIdentifier:@"AppCellID"];
-
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
AppCell *cell = [tableView dequeueReusableCellWithIdentifier:@"AppCellID" forIndexPath:indexPath];cell.model = self.dataArray[indexPath.row];
return cell;
}