您的位置:首页 > 产品设计 > UI/UE

第08章 表视图UITableView简介

2014-12-20 13:20 330 查看
UITableView表视图

UITableViewCell表视图单元

UITableViewDelegate
UITableViewDataSource

可以在UITableViewCell中添加子视图,从而在一个单元中放置更多的数据。
可以通过代码,或者在nib文件中加载他们。

两种基本样式:
分组表(grouped table):每个组都由嵌入在圆角矩形中的多个行组成。
无格式表(plain table):默认的样式,没有圆角矩形,如果使用了索引,又称为索引表。

表中的每个部分,称为数据源中的分区(section)。
分组表中,每个分组都是一个分区。
索引表中,每个索引都是一个分区。

iphone human interface guidelines中,不建议创建带有索引的分组表。

关键词

UITableView

- (void)registerClass:([code]Class
)
cellClass
forCellReuseIdentifier:(
NSString *
)
identifier

- (id)dequeueReusableCellWithIdentifier:([code]NSString *
)
identifier


UITableViewCell
textLabel

NSIndexPath
section
row

UITableViewDataSource
numberOfRowsInSection
cellForRowAtIndexPath

UITableViewDelegate

willSelectRowAtIndexPath

didSelectRowAtIndexPath

一个简单的表视图例子
1. 使用模板single view application创建工程
2. 向xib中拖入一个table view 实例,并关联委托和数据源到file's owner






Table View Data Source数据源方法

static NSString *simpleTableIdentifier = @"SimpleTableIdentifier";

[self.tableView registerClass:[UITableViewCell class]

forCellReuseIdentifier:@"HYDTableViewCell"];

获取某个分区中,有多少行

-(NSInteger)tableView:(UITableView *)tableView

numberOfRowsInSection:(NSInteger)section

获取某个分区中的某行的表视图单元

-(UITableViewCell *)tableView:(UITableView *)tableView

cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

static NSString *simpleTableIdentifier = @"SimpleTableIdentifier";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

//if (cell==nil) {

// cell = [[UITableViewCell alloc]

// initWithStyle:UITableViewCellStyleDefault

// reuseIdentifier:simpleTableIdentifier];

//}

cell.textLabel.text = self.dwarves[indexPath.row];

return cell;

}

NSIndexPath:row,section

dequeueReusableCellWithIdentifier为表视图单元重新利用
当表视图单元滚离屏幕时,它们将被放置在一个可重用的单元队列中,以便后面重新利用,避免了重复创建和销毁。
如果系统运行较慢,则会清理这些单元,以释放存储空间。

添加一个图像

UIImage *image = [UIImage imageNamed:@"star.png"];

UIImage *highlightImage = [UIImage imageNamed:@"star2.png"];

cell.imageView.image = image;

cell.imageView.highlightedImage = highlightImage;



UITableViewCell属性

imageView:文本左侧的图像

textLable:文本
detailTextLable:详细文本,通常用作解释性的说明

自带样式

UITableViewCellStyleDefault:默认样式,只显示左侧图像和文本



UITableViewCellStyleSubtitle:在文本下方显示详细文本



UITableViewCellStyleValue1:在右侧显示详细文本



UITableViewCellStyleValue2:不显示图像,并将详细文本粗体显示在文本右边(居中)



以上都为数据源方法,用来向表视图提供数据。
下面介绍委托方法,来控制表示图的外观和处理用户交互

控制缩进:

-(NSInteger)tableView:(UITableView *)tableView

indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath

更改字体大小和行高
表视图自身有个rowHeight属性,其控制所有行的行高
而这个委托方法,可控制某行的行高

cell.textLabel.font = [UIFont systemFontOfSize:50];

- (CGFloat)tableView:(UITableView *)tableView

heightForRowAtIndexPath:(NSIndexPath *)indexPath

选中:
某行将会被选中

-(NSIndexPath *)tableView:(UITableView *)tableView

willSelectRowAtIndexPath:(NSIndexPath *)indexPath

某行已经被选中

-(void)tableView:(UITableView *)tableView

didSelectRowAtIndexPath:(NSIndexPath *)indexPath

定制表示图单元:
代码方式(其实就是添加UITableViewCell子类,然后向其添加子视图)
1.通过single view application创建xcode项目Cells
2.添加新单元:创建类BIDNameAndColorCell,继承自UITableViewCell

3.为cell添加子视图

改写如下方法

- (id)initWithStyle:(UITableViewCellStyle)style

reuseIdentifier:(NSString *)reuseIdentifier

{

self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

if (self) {

//添加子视图

CGRect nameLabelRect = CGRectMake(0, 5, 70, 15);

UILabel *nameLabel = [[UILabel alloc] initWithFrame: nameLabelRect];

nameLabel.textAlignment = NSTextAlignmentRight;

nameLabel.text = @"Name:";

nameLabel.font = [UIFont systemFontOfSize:12];

[self.contentView addSubview: nameLabel];

………

}}

此时通常会遇到一个问题,cell中某些控件的值,通常是需要用户在创建出此cell后,通过cell属性来设置,

而初始化此cell的时候,这些暴露给用户的属性暂时为空的,用户还没来得及设置,

解决此问题的办法是,修改这些属性的setter,当用户设置或者修改这些属性的时候,将值重新赋给控件的某个属性。

那么此时,就需要在代码中获取某子视图的指针,以往在c++中通常是定义一个私有指针变量,来保持此变量

在oc也一样,定义一个控件的私有变量,注意,定义为私有,就会不会暴漏给外部,

此时只需要定义为实例变量即可,而不需要使用property,不过其实也可以定义为私有的outlet

类的数据成员,在类中,直接访问, _XXX

类的属性,在类中,使用self.xxx访问

如果需要在控制器类的.m中获取某子视图指针,有两种方法:
1.为此子视图定义输出口,关联xib文件中子视图实例(此种方法,外部可获取到此子视图属性)
2.为其定义私有的输出口(在.m无名类扩展中)
3.UITableView *tableView = (id)[self.view viewWithTag:1];

其实就类似与MFC,当想让外界访问到子控件时,定义成员变量,DDX/DDV
外界不需要访问此子控件,而内部又要使用的时候,采用GetDlgItem获取

关于cell 的reuse
1.提前在viewDidLoad中,通过tableView为某类型的cell,注册可重用标识符

[tableView registerClass:[BIDNameAndColorCell class]

forCellReuseIdentifier:@"HYDCELL"];

此时,以后采用dequeueReusableCellWithIdentifier所获取的cell肯定非空,不用判空。

2.采用之前的方法,不在viewDidLoad中提前注册,而是在init cell的时候,为其设置可重用标识符

static NSString *simpleTableIdentifier = @"HYDCELL";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];

if (cell==nil) {

cell = [[UITableViewCell alloc]

initWithStyle:UITableViewCellStyleDefault

reuseIdentifier:simpleTableIdentifier];

}

但是有个问题,此时传入的类型UITableViewCellStyleDefault起什么作用?所以说,如果是定制类型的cell,不应该采用此方法。
应该统一在viewDidLoad中,
采用registerClass: forCellReuseIdentifier为纯代码的Cell注册可重用标识符,
采用registerNib: forCellReuseIdentifier为xib方式的Cell注册可重用标识符

xib方式(新建UITableViewCell子类,关联,注册xib文件)
1. 创建UITableViewCell子类BIDXibCell
2. 创建XibCell.xib
3. 拖入一个Table View Cell
4. 修改关联类型为BIDXibCell,修改行高为65, 修改其可重用标识符





注意,在表视图中,还应该使用viewTable的属性rowHeight修改表视图的行高,表视图单元的行高和表视图的行高是两个概念。
而且,表视图的行高属性,修改后,则所有行统一修改。
使用委托方法,heightForRowAtIndexpath,则可修改某行的高度

5. 拖入子控件,向其关联的自定义类型中关联输出口





6. 为此xib定义的表视图单元注册可重用标识符(viewDidLoad中)

UINib *nib = [UINib nibWithNibName:@"XibCell" bundle:nil];

[self.tableView registerNib: nib forCellReuseIdentifier:@"CellTableIdentifire”];

最后,回过头来,哪种方式定义的cell比较好?

个人认为是纯代码方式,因为这种好复用,只有一个类型,不像xib方式,还得绑定一个xib文件。

分组表,多分区

使用Single View Application创建工程,Sections

向xib中拖入一个table view,格式改为grouped

将名为sortednames.plist(单词表)的文件拖入工程

@property (copy, nonatomic) NSDictionary *names; //all data
@property (copy, nonatomic) NSArray *keys; //all keys

- (void)viewDidLoad
{
[super viewDidLoad];
UITableView *tableView = (id)[self.view viewWithTag:1];
[tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:SectionsTableIdentifier];
NSString *path = [[NSBundle mainBundle] pathForResource:@"sortednames" ofType:@"plist"];
self.names = [NSDictionary dictionaryWithContentsOfFile: path];
self.keys = [[self.names allKeys] sortedArrayUsingSelector: @selector(compare:)];
}

#pragma mark -
#pragma mark Table View Data Source Methods

//分区数量
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView ;

//某个分区的行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section ;

//某个分区的title
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;

//获取某个位置的表视图单元
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath;

其实创建多个分区很简单,实现响应的数据源方法即可。

索引表

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return self.keys;
}
添加索引更简单,实现以上数据源方法即可。

The returned array must have the same number of entries as you have sections, and the values must correspond to the appropriate section.
不过此数组需要跟表视图中,各分区完全匹配。

总结:
1.大量的委托方法,实现tableView的数据源和委托

2.自定义的Controller,关联一个xib,其中有一个UITableView
此时,如果要自定义Cell样式,有两种方法:
2.1.代码方式,创建UITableViewCell子类,在其init中添加子视图,
在controller中的viewDidLoad中为此cell registerClass,进而可以获取到该类型的cell

2.2.xib方式,创建一个xib,包含一个UITableViewCell, 利用IB修改界面
然后在controller中的viewDidLoad中为此cell registerNib,进而可以获取到该类型的cell
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: