Navigation Controller和 Table View
UITableView Section 0 Row 0 Row 1 Row 2 Row 0 Row 1 . Section 1 接著這個範例就是IPhone常見的表格,可以設定表格的圖案、文字、Label、Cell、Section等屬性。 Cell就是此表格的一格欄位,Section 就是多個欄位所組成的群組。 Row 0 Row 1 . Section 1
Row 0 Row 1 Row 2 Table View表格本身有包含Header View及Footer View欄位可以添加,每個Section本身也有Section Header View及Section Footer View欄位可以添加。 Row 0 Row 1 .
空白專案建立Single View App 建立空白專案 首先創建一個SingleView專案
Table View Controller 將圖片拉入專案中 先將藥用的圖片直接拖拉入專案中
Table View Controller 刪除SingleView,換成TableView 將原本的SingleView Controller選取並刪掉,右下方選取Table View Controller並拖拉進畫面中。
增加一個Cocoa類別檔案 Class TableViewController Subclass UITableViewController 為了控制這個Table View Controller,新建一個Cocoa Class,名稱為TableViewController,類別為UITableViewController。
設定頁面對應的Class Property 然後記得設定此Table View Controller頁面所相關連到的Table View Controller。
設定Cell對應的Identifier 接著為了針對表格內的欄位做操作,點選一格欄位並設定identifier屬性為 My_Cell_ID。
TableViewController.m @implementation TableViewController { NSMutableArray *data; } 在TableViewController.m檔案中的implementation 範圍內加入一個區域陣列變數,NSMutableArray *data; 並在初始化函式中將此陣列變數初始化,data = [[NSMutableArray alloc] init]。 -(void)ViewDidLoad { [super viewDidLoad]; data = [[NSMutableArray alloc] init]; }
Section、Header、footer UITableViewDataSource (NSInteger)numberOfSectionsInTableView:(UITableView *) tableView 回傳此表格有幾個section (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 回傳此section有幾格 (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 回傳此section的表頭字串 - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section 回傳此section的表尾字串 為了設定表格的顯示結果,我們一定要實作這兩個函式,numberOfSectionsInTableView、numberOfRowsInSection,而另外兩個函式titleForHeaderInSection及titleForFooterInSection則非必要,若不想顯示Header及Footer則可以不用寫。
TableViewController.m - (NSInteger)numberOfSectionsInTableView:(UITableView *) tableView { return 2; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if(section == 0){ return 3; } else{ return 5; 例如我們這個範例想要顯示兩個Section,於是在numberOfSectionsInTableView函式中,回傳2。 接著在numberOfRowsInSection函式中,設定第一個Section群組中擁有三個欄位,第二個Section群組中則有五個欄位。
TableViewController.m -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{ if(section == 0) return @"Section 1 Header"; else return @"Section 2 Header"; } - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{ return @"Section 1 Footer"; return @"Section 2 Footer"; 接著設定Section的Header及Footer要顯示的文字
建立表格 - (UITableViewCell *)tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath 表格每一行稱為一個cell,iPhone表格設計上,一次 只配置看得到的cell,若一次只能顯示10筆,會呼叫 tableView: cellForRowAtIndexPath:10次 UITableViewCell:定義cell上顯示的內容 Property UILabel *textLabel :可指定表格上顯示UILabel UILabel *detailTextLabel:可指定表格上顯示的詳細的UILabel UIImageView *imageView :可指定表格上顯示的UIImageView 顯示表格欄位的方式預設有很多種,只要通過UITableViewCell設定參數即可改變要顯示的內容。
UITableViewCellStyle Property UITableViewCellStyleDefault UITableViewCellStyleValue1 UITableViewCellStyleValue2 UITableViewCellStyleSubtitle 這邊有四種預設的欄位可以選擇,預設為第一種,有圖片及Title。 15
建立表格內容 [data removeAllObjects]; -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if([indexPath row]==0) [data removeAllObjects]; NSString *log = [NSString stringWithFormat:@"Section %ld-%ld",[indexPath section]+1,[indexPath row]+1]; [data addObject:log]; UITableViewCell *cell=cell=[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:@"My_CELL_ID"]; [cell.imageView setImage:[UIImage imageNamed:@"apple-icon"]]; cell.textLabel.text = [data objectAtIndex:[indexPath row]]; return cell; } 在cellForRowAtIndexPath函式中,撰寫程式來決定如何顯示我們的欄位,此程式碼將指定欄位的文字顯示為” Section X-X”,代表第幾個Section群組及row欄位,接著指定欄位的顯示種類為” UITableViewCellStyleDefault”預設值,並設定此Cell欄位圖片及文字。
選擇表格某一行事件 實作UITableViewDelegate 參數indexPath的cell被選取 (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *) indexPath 參數indexPath的cell被選取 要是想要在選擇Cell欄位時產生事件,可以呼叫didSelectRowAtIndexPath。
didSelectRowAtIndexPath - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *) indexPath { NSString *log = [NSString stringWithFormat:@"Section %ld-%ld",[indexPath section]+1,[indexPath row]+1]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Cell" message:log delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; } 像是這樣,在點擊一格Cell欄位時,會產生一個提示視窗,告訴使用者被點擊的Cell欄位的section及row。
Cell didSelectRowAtIndexPath 用alertView顯示被選取 到的section和row 當點擊第一個Cell欄位時,顯示此第一個Cell欄位屬於Section 1及第一個row。
Cell.accessoryType UITableViewCellAccessoryNone, Property UITableViewCellAccessoryNone, UITableViewCellAccessoryDisclosureIndicator, UITableViewCellAccessoryDetailDisclosureButton, UITableViewCellAccessoryCheckmark, UITableViewCellAccessoryDetailButton Cell欄位也可以設定右邊可以點擊的圖案按鈕效果,像是右邊有提示、打勾、Detail等等。 ihsuan.peng@gmail.com
UITableViewCellAccessoryType Property UITableViewCellAccessoryNone 附加cell的類型,預設沒有 若透過accessoryView 屬性設定自定的view,此屬性會被忽 略 UITableViewCellAccessoryDetailDisclosureButton and UITableViewCellAccessoryDetailButton類型時,按鈕被按下 會會觸發 tableView:accessoryButtonTappedForRowWithIndexPath:事件 若是有設定Cell.accessoryType,則按下Cell欄位的右邊圖案時,就會觸發accessoryButtonTappedForRowWithIndexPath函式。
accessoryButtonTappedForRowWithIndexPath - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { NSString *log = [NSString stringWithFormat:@"Section %ld-%ld",[indexPath section]+1,[indexPath row]+1]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Detail" message:log delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; } 這裡跟做法跟didSelectRowAtIndexPath一樣,點擊以後告訴使用者被點擊的Cell欄位的section及row。
accessoryButtonTappedForRowWithIndexPath 用alertView顯示被選取 到的section和row 像這樣,在點擊右邊的提示訊息時,就會呼叫accessoryButtonTappedForRowWithIndexPath,出現提示視窗。
TextView TextView範例 範例檔案: TextView
Storyboard--Navigation Controller ihsuan.peng@gmail.com
空白專案建立Single View App 建立空白專案 接下來要做的是有關Navigation的範例,一樣我們產生新的SingleView專案
Table View Controller 刪除SingleView,換成TableView 一樣刪掉SingleView Controller頁面,改成Table View Controller 頁面
增加一個Cocoa類別檔案 Class TableViewController Subclass UITableViewController 產生相對應的UITableViewController Class
設定頁面對應的Class Property 記得讓頁面與UITableViewController相對應。
嵌入Navigation Controller
UINavigationItem Property NSString *title UIView *titleView 設定標題字串,放在 navigation bar的中間 UIView *titleView 設定自定的標題View,若有設定此屬性,會取代 title屬性 若leftBarButtonItem 不是nil,此屬性會被忽略 UIBarButtonItem *leftBarButtonItem 設定navigation bar左邊的元件 UIBarButtonItem *rightBarButtonItem 設定navigation bar右邊的元件 Navigation Controller有四個屬性,標題文字、標題圖案、左邊按紐、右邊按紐
修改頁面標題 設定Navigation Controller的文字標題為 Page 1
加入導覽按鈕 這邊可以直接拖拉Bar Button Item來添加按紐
self.navigationItem.leftBarButtonItem 左上方按鈕 self.editButtonItem; 這裡我們拖拉一個左上方按紐,Edit
TableViewController.m @implementation TableViewController { NSMutableArray *dataArray; } -(void)ViewDidLoad { [super viewDidLoad]; dataArray = [[NSMutableArray alloc] init]; [dataArray addObject:@"Red"]; [dataArray addObject:@"Green"]; … self.navigationItem.leftBarButtonItem = self.editButtonItem; } 這裡我們採用固定資料,將一個各種顏色的文字陣列顯示在TableView中,並設定此navigation的左邊按紐為Edit按鈕。
navigation bar的兩種編輯模式 有新增和刪除,預設為刪除 由UITableViewDelegation中tableView: editingStyleForRowAtIndexPath:的回傳值決定 (UITableViewCellEditingStyle)tableView:(UITableView *) tableView editingStyleForRowAtIndexPath: (NSIndexPath *) indexPath 接著我們可以讓此Edit按鈕觸發editingStyleForRowAtIndexPath函式,可以選擇兩種編輯模式,新增或是刪除。
新增刪除模式設定 typedef enum { UITableViewCellEditingStyleNone, UITableViewCellEditingStyleDelete, UITableViewCellEditingStyleInsert } UITableViewCellEditingStyle; 在此函式若是回傳UITableViewCellEditingStyleDelete,則是刪除一格欄位,若是UITableViewCellEditingStyleInsert,則會新增一格欄位。 -(UITableViewCellEditingStyle) tableView:(UITableView *) tableView editingStyleForRowAtIndexPath: (NSIndexPath *) indexPath{ return UITableViewCellEditingStyleInsert; return UITableViewCellEditingStyleDelete; }
self.navigationItem.leftBarButtonItem 當點選Edit按鈕時,左邊就會新增圖示並在點擊Cell欄位時分別作相對應的動作,新增或是刪除
UITableViewDataSource 新增/刪除表格 (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle) editingStyle forRowAtIndexPath: (NSIndexPath *) indexPath 當做新增或刪除cell時會執行此方法,在此方法中需實作資 料的新增和刪除 (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath 回傳是否可以編輯此indexPath的cell 當選擇新增或是刪除時,就會先判斷是否可以編輯此Cell欄位,呼叫canEditRowAtIndexPath,若此函式回傳為true,則會觸發函式commitEditingStyle,在此函式實作資料的新增及刪除。
editingStyle forRowAtIndexPath (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle) editingStyle forRowAtIndexPath:(NSIndexPath *) indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { [dataArray removeObjectAtIndex:[indexPath row]]; [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { [dataArrayinsertObject:@"add Data" atIndex:[indexPath row]]; [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 這裡示範新增及刪除,首先判斷當前是新增還是刪除的動作。若是刪除,則在我們固定的字串陣列中刪除我們點選的那格Cell欄位的相對應字串物件,接著呼叫[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 來產生刪除的動畫。 若是新增,則在我們固定的字串陣列中新增一個文字陣列,在我們點選的那格Cell欄位的位置,接著呼叫[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];來產生新增的動畫。
editingStyle forRowAtIndexPath 刪除的動畫就如這樣,當點擊Blue欄位時,整個欄位會滑向左邊,並在右邊增加一個按鈕,讓使用者點擊,確認要刪除,一刪除則Blue欄位會消失,下方的欄位會擠上來。
editingStyle forRowAtIndexPath 新增的動畫就如圖所示,按下Red欄位時,會在此位置新增一格add Data欄位,並將原本的Red擠到下方。
UITableViewDataSource 移動表格順序 Reordering Table Rows (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *) indexPath 回傳是否可以移動此indexPath的cell (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *) fromIndexPath toIndexPath:(NSIndexPath *) toIndexPath 設定可移動後當移動cell時會執行此方法 也可以設定每一格欄位是否可以移動,先在canMoveRowAtIndexPath函式中判斷是否可以移動,若回傳為Yes時,就會呼叫moveRowAtIndexPath來實作移動的方法。
(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { return YES; } (void)tableView:(UITableView *)tableView moveRowAtIndexPath: (NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *) toIndexPath NSUInteger fromRow = [fromIndexPath row]; NSUInteger toRow = [toIndexPath row]; id object = [dataArray objectAtIndex:fromRow]; [dataArray removeObjectAtIndex:fromRow]; [dataArray insertObject:object atIndex:toRow]; 例如這樣子寫,在canMoveRowAtIndexPath回傳Yes,並在moveRowAtIndexPath設定要移動的欄位以及要移動到哪一格欄位,相當於先刪除要移動的欄位,接著在要移動到的地方新增一格欄位
canMoveRowAtIndexPath 這就是移動的動畫效果,按住Cell欄位並移動時,就可以移動欄位。
Edit TextView 範例檔案: Edit TextView