一、創建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;//控制指定分區的頁腳控件的大小