一、创建TableView
TableView在iOS的开发中,是最为常用的UI控件,其实质是一个列表。其包含了如下功能:
数据的收集由实现了<UITableViewDataSource>协议的类提供。
处理Action事件由实现了<UITableViewDelegate>协议的类提供。
1.1 从StoryBoard和属性中认识TableView
先从StoryBoard中创建一个UITableView,来来看它可变属性分别代表着什么。
分别解释一下每项的具体意思:
1、Content和Prototype Cells
Content选项是用于定义开发者创建的TableView是动态表格还是静态表格。Dynamic Prototypes是动态,Static Cells是静态。Dynamic Prototypes是动态单元格的模版。
2、Style
TableView有两种Style,分别为Plain和Grouped。Plain意思是表格使用系统默认Style,也就是无分组的类型。Grouped则是分组类型。
3、Separator
是指Cells与Cells之间的分割线,其有Style属性:Single Line(单线)、Single Line Etched(被蚀刻的单线)、Default(系统默认)、Color属性和Separator Inset属性:控制分割线长度。
4、Selection
控制Cells被选中时的处理,有三个可选值,分别为:NO Selection:不允许选中、Single Selection: 只允许单选、 Multiple Selection:允许多选。
5、Editing
Editing是表示TableView处于可编辑状态,其下有三个值可供选择,分别为:No Selection: During Editing:处于编辑状态不允许选中、Single Selection During Editing:处于编辑状态允许单选、Multiple Selection During Editing:处于编辑状态时允许多选。
tableView的属性介绍:
self.tableView.style//只读属性,用于返回该表格的样式。
self.tableView.rowHeight//该属性用语返回或设置表格的行高。
self.tableView.separatorStyle//该属性用语返回或设置表格的分割条样式
UITableViewCellSeparatorStyleNone//无分隔条
UITableViewCellSeparatorStyleSingleLine//单线分隔条
UItableViewCellSpearatorStyleSingleLineEtched//被蚀刻的单线分隔条
self.tableView.separatorColor//该属性用语设置分隔条的颜色
self.tableView.backgroundView//该属性用于返回或设置表格的背景控件
self.tableView.tableHeaderView//该属性可设置或返回该表格的页眉控件
self.tableView.tableFooterView//该属性可设置或返回制定分区包含的行数
1.2TableView的DataSource
先来看看Table的结构示意图:
从这张图中,我们可以知道UItableView直接管三个东西,分别是:UITableViewCell、UITableViewDataSource和UITableViewDelegate。
其中UITableViewCell是TableView主要视图控件,其主要功能是提供Cell的各种设置和提供定制类型的Cell,如何定制Cell将在本文的下一节中探讨。
UITableViewDataSource主要是为UITableView提供数据源,有了这些数据源,UITableView才能显示复合预期的内容。
我跳到UITableViewDataSource协议的接口文件,来看一下,DataSource可以为我们提供哪些内容。在协议协议中,我们看到,定义了一个NSIndexPath类,其主要作用是提供为开发者提供Cell的索引。
@interface NSIndexPath (UITableView)
+ (instancetype)indexPathForRow:(NSInteger)row inSection:(NSInteger)section;//类方法,作用是通过提供一个row和section属性初始化一个NSIndexPath对象,可以用来表示某一个Cell。
@property (nonatomic, readonly) NSInteger section;//表明Cell处于哪个section段中,是只读属性
@property (nonatomic, readonly) NSInteger row;//表明在section段中的行数,是只读属性
@end
再来看看其中的@required方法。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;//这个方法的返回值确定TableView在一个Section中显示多少个Cell。
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier: **翻译:Row显示。开发者应该总是通过设置每个Cell的reuseIdentifier和dequeueReusableCellwithIdentifier:方法,来重用细胞。这句话显示了苹果希望开发者自定义自己的Cell。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;//这个方法将提供如何显示Cell,返回的对象将会显示在TableView上。
再来看看老师在课堂上讲的其它常用方法。
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView//这个方法的返回的值确定在TableView中有几个Section。*特别提醒,如何没有提供这个方法,程序将会自动返回1。
—(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath // Return NO if you do not want the specified item to be editable.//苹果已经为我们说明了这个方法的作用,如何返回NO的话specified item将无法被编辑。
(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view//这段代码意思是先判断开发者提供的UITableViewCell是删除按钮还是增加按钮,然后进入编辑模式,并且调用tableView自带的删除和增加方法。
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath//实现这个方法的目的是在删除和增加了一个Cell后,Cell如何实现位置的移动。
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
// Return NO if you do not want the item to be re-orderable.//如果返回NO,item将不会被重构。
导航搜索条也是在DataSource中实现的,其实现的关键是提供三个方法:
-(NSArray*)sectionIndexTitlesForTableView:(UITableView *)tableView//他的返回值是一个数组,数组的每个元素,就是导航搜索条的每一项。
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section//提供每个Header显示的东西
-(NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index//提供通过导航搜索条条转的方法
1.3 TableView的Delegate
UITableViewDelegate是为TableView提供Events的解决方法,这个协议中所有的方法都是@optional。
其中有几个比较关键的方法,需要写下来:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self performSegueWithIdentifier:@"PassValue" sender:indexPath];
}//这个方法主要是提供Cell的点击事件,如果用户点击了Cell,将返回这个方法中的代码
使用Delegate的方法再配合Segue的方法,可以将不同Cell的值传给下一个界面,这也是本次通讯录作业中比较关键的代码,下面就是如何实现Cell的传值的代码。是通过Segue的传值,和indexPath属性来唯一确定一个Cell,并且传值给下一个。
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"PassValue"]) {
UITableView * tv=(UITableView* )sender;
ViewController * vc=(ViewController*)segue.destinationViewController;
vc.toName=self.NameData[[tv indexPathForSelectedRow].row];
vc.toNumber=self.NumberData[[tv indexPathForSelectedRow].row];
vc.row=[tv indexPathForSelectedRow].row;
}//这段代码比较关键的地方是:vc.toName=self.NameData[[tv indexPathForSelectedRow].row]; 后面的 [indexPathForSelecteRow].row意思是返回选中Cell的row值,我的工程是比较简单的,数组中的索引一一对应TableView中Cell的row值,所以返回row当作数组的索引,就能简单的返回指定Cell中显示的数据(Section是1,如果不为1,那么返回的索引应该是Section+row)
再来看看视屏中介绍的其它Delegate方法对应的TableView的事件处理方法:
这是老师视频中综合介绍Delegate各项方法的合集,很详细,在此不在敖述了。
1.4 定制Cell
如果只是使用系统提供的UITableViewCell,UITableView控件的表格行只支持有限的样式,而且每个表格行只包含textLabel、detailTextLabel、UIImageView 这三个控件。所以在开发实践中DIY自己的Cell是普遍的做法。
由于对于xib不是很熟悉,在看完视频后,决定学会掌握前面两种定制Cell的方法,分别是:
1、继承UITAbleViewCell定制Cell。通过继承UITableViewCell来添加任意控件,设置任意样式。
2、使用动态单元格原型定制Cell。在本次通讯录的作业中,笔者就使用了这种方法,由于是在Interface Builder中定制Cell,所以感觉非常方便,而且只要在Cell属性中,为identifier添加一个值,就可以使用前面提到的dequeueReusableCellWithIdentifier:方法,使用Cell,所以感觉十分方便。
在经过一段时间的学习后,感觉最适合我的定制Cell方法是将前文提到的两种方法结合使用,来定制Cell。这样定制的Cell使用起来十分方便,而且独立性很高,也方便复用,具体的定制方法,不在多说了。只要按照老师讲的视频练习几遍,比看上百份介绍方法更为可靠和实用。关键只有一点,自己拖控件在Cell上时,不太方便访问到控件时,用可通过调用Tag方法来访问控件,示列代码如下:
UILabel * Name=(UILabel*)[cell viewWithTag:1];//通过 ViewWithTag:获取到对象控件,再强制转会类型,将其对象赋予一个实例对象来访问内部的属性。
二、CollectionView
通过对CollectionView的认识,应该说CollectionView是TableView的扩展,是在对其在原用的基础上,加强对于美化界面的能力。也就说CollectionView中的许多可设置项都可以在TableView中找到相似的设置。
先来看看其最基本的界面构成:
可以看到,CollectionView基本模版是模仿书架做的,其中的“书”就是collectionView的Cells了。
这里重点看一下CollectionView的比较重要的组成部分
1、Items:该属性用于设置UICollectionView的单元格原型的数量。想同于TableView中的Cell。
2、Layout:该属性用于指定UICollectionView所使用的布局对象,它可以支持Flow、Custom两个属性,如果指定Flow属性值,则表明使用UICollectionView FlowLayout布局对象;如果指定Custom属性值,则表明会使用自定义的UICollectionViewLayout布局对象。
3、Scroll Direction:该属性实际上来自于UICollectionViewFlowLayout布局对象,如果将Layout属性设置为“Custom”属性值,该下拉属性选择器就会消失。该属性用于设置该控件的滚动方向,它支持Vertical和Horizontal两个属性值,分别代表垂直滚动和水平滚动。
4、Accessories: 该属性置顶是否显示UICollectionView分区的Supplementary Views和Decoration View。
应该说CollectionView最为重要的就是其界面的布局了,每个Item的位置是交给UICollectionViewFlowLayout来管理的,每当要创建一个Item时,CollectionView都会向UICollectionViewFlowLayout要Item的显示位置,所以学好CollectionView必须掌握UICollectionViewFlowLayout中的常用方法,下面收集了一些常用方法,分享给同学(这些方法均是在协议<UICollectionViewDelegateFlowLayout>中):
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath;//该方法返回的CGSize值,将控制指定NSIndexPath对应的单元格大小
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section;
//该方法返回的UIEdgeInsets对象将控制指定分区上下左右空白区域的大小
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;//控制指定分区内最小的行间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;//值将控制指定分区内最小的行间距。
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section;//控制指定分区的页眉控件的大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;//控制指定分区的页脚控件的大小