在此之前,我們已經創建了一個通過簡單的表視圖應用程序並顯示預定義的圖像。在本教程中,我們將繼續努力,使應用程序變得更好,:
>不同的行顯示不同的圖像 - 上個教程,我們的所有行顯示相同的縮略圖。那么不同的食物顯示不同的圖片不是更好么?
>自定義視圖單元-我們將展示我們自己的視圖來替代默認表單元格樣式
顯示不同縮略圖
在我們更改代碼之前,讓我們回顧顯示縮略圖的代碼。
最后,我們增加了一個行代碼指示UITableView每一行顯示“creme_brelee.jpg”這張圖片。顯然,為了顯示不同的圖像,我們需要改變這行代碼。正如之前解釋的那樣,IOS在顯示一條表單元格時自動調用“cellForRowAtIndexPath”方法
1
|
-
(UITableViewCell
*
)tableView
:
(UITableView
*
)tableView cellForRowAtIndexPath
:
(
NSIndexPath
*
)indexPath
|
看看該方法的參數,每次調用時通過“indexPath”來傳遞表單元格信息。indexPath參數包含的表單元格的行數(以及節號)。您可以簡單地使用“indexPath.row”屬性,找出當前指向哪一行。和數組一樣,表行的計數從零開始。換言之,對於第一行“indexPath.row”返回0。
因此,為了顯示不同的縮略圖,我們將添加一個新的數組(即縮略圖),存儲文件名的縮略圖:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@implementation
SimpleTableViewController
{ NSArray *tableData; NSArray *thumbnails; } - ( void )viewDidLoad { [super viewDidLoad ]; // Initialize table data tableData = [ NSArray arrayWithObjects : @ "Egg Benedict", @ "Mushroom Risotto", @ "Full Breakfast", @ "Hamburger", @ "Ham and Egg Sandwich", @ "Creme Brelee", @ "White Chocolate Donut", @ "Starbucks Coffee", @ "Vegetable Curry", @ "Instant Noodle with Egg", @ "Noodle with BBQ Pork", @ "Japanese Noodle with Pork", @ "Green Tea", @ "Thai Shrimp Cake", @ "Angry Birds Cake", @ "Ham and Cheese Panini", nil ]; // Initialize thumbnails thumbnails = [ NSArray arrayWithObjects : @ "egg_benedict.jpg", @ "mushroom_risotto.jpg", @ "full_breakfast.jpg", @ "hamburger.jpg", @ "ham_and_egg_sandwich.jpg", @ "creme_brelee.jpg", @ "white_chocolate_donut.jpg", @ "starbucks_coffee.jpg", @ "vegetable_curry.jpg", @ "instant_noodle_with_egg.jpg", @ "noodle_with_bbq_pork.jpg", @ "japanese_noodle_with_pork.jpg", @ "green_tea.jpg", @ "thai_shrimp_cake.jpg", @ "angry_birds_cake.jpg", @ "ham_and_cheese_panini.jpg", nil ]; } |
正如你可以從上面的代碼中看到的,我們用圖像文件名列表初始化了的縮略圖數組。圖像的順序排列與“tableData”對齊。
為了您的方便,您可以下載該圖像包,並把它們添加到您的項目,確保“Copy items into destination group’s folder”已勾選當然你也可以用自己的圖片。
添加的圖像文件后,你應該會在Project Navigator中發現他們,如下面的屏幕:
最后,更改在cellForRowAtIndexPath“方法的代碼:
1
|
cell.imageView.image
=
[
UIImage的imageNamed
:
[
縮略圖objectAtIndex
:
indexPath.row
]
]
;
|
什么是 [thumbnails objectAtIndex:indexPath.row]?
這行代碼獲取特定行的圖像名字。就是說,indexPath.row屬性對於第一行返回0,我們使用“objectAtIndex”的方法選取圖像數組的第一個(即egg_benedict.jpg)。
保存所有的更改后,再次嘗試運行您的應用程序。現在應該不同的表中單元格顯示縮略圖:
自定義表格視圖單元格
應用程序是否可以更好看?我們將通過自定義表格單元格使其更好看。到目前為止,我們使用的默認樣式顯示表單元格,而且縮略圖的位置和大小是固定的。如果你想就像下面的屏幕顯示的那樣使縮略圖更大並附上每個菜的准備時間,怎么辦?

不同風格的自定義表格視圖單元格
設計單元格
在這種情況下,你必須創建和設計自己的表格單元格。返回到Xcode。在項目瀏覽器中,右鍵單擊“SimpleTable”文件夾並選擇“New File ...”。
為了設計我們自己的表格單元格,我們要創建一個新的表格單元格界面生成器。在這種情況下,我們只需要啟動一個“空”的用戶界面。點擊“下一步”繼續。

選擇一個空的Interface Builder文檔
當提示選擇設備系列時,選擇“iPhone”,然后單擊“下一步”繼續。保存的文件為“SimpleTableCell”。
一旦該文件被創建時,你就能在Project Navigator中找到它。選擇“SimpleTableCell.xib”切換到界面生成器。我們要設計的自定義表格單元格的外觀。
在對象庫中,選擇“Table View Cell(表格視圖單元格)”,將其拖動到界面生成器的設計區域。
為了容納更大的縮略圖,我們要改變單元格的高度。只要按住下/上側的單元格邊緣並縮放到高度78。
或者,您也可以使用“Size Inspector”改變高度。

表查看單元格的尺寸督察
下一步,選擇“Attributes Inspector(屬性檢查器)“的上半部分的通用區域來為自定義單元格“SimpleTableCell”設置“Identifier(標識符)”。這個標識符將在后面的代碼中使用。
表格單元格視圖配置好之后,我們將往他里面放其他元素。選擇“Image View”,並把它拖到表視圖單元格。
image view用於顯示縮略圖。您可以調整其大小,使其適合單元格。參考數值,我設置的高度和寬度為69像素。
接下來,我們將添加三個標簽:Name(姓名),Prep Time(准備時間)和Time(時間)。“Name”標簽將用於顯示配方的名稱。“Prep Time”是一個靜態的標簽,只顯示“准備時間”。最后,“Time”的標簽是一個動態的標簽被用於顯示實際的具體菜餚的准備時間。
要添加一個標簽,在Object library(對象庫)中選擇“標簽”,將其拖動到單元格中。您可以雙擊標簽以更改其名稱。
和上面所顯示的做比較,您可能會發現您的字體大小和樣式是不同的。要更改字體樣式,只需選擇標簽並選擇“Attribute Inspector(屬性檢查器)”。從這里,你可以改變“字體”和最小字體大小的設置。您也可以通過檢查更改文本顏色和對齊方式。
您的最終設計應該類似於這樣:
創建一個類的自定義單元格
到目前為止,我們已經設計了表格單元格。但如何才能改變自定義單元格的標簽值嗎?我們要為自定義表視圖單元格創建一個新的類。這個類代表了自定義單元格的底層數據模型。
就像以前一樣,右鍵單擊“SimpleTable的項目瀏覽器”文件夾中,然后選擇“新建文件”。

選擇一個新的文件模板
選擇該選項后,Xcode會提示你選擇一個模板。我們要創建一個新的自定義表格視圖單元格類,選擇“Objective-C類”下的“Cocoa Touch”,然后單擊“下一步”。

為您的項目創建新的文件
類名填寫“SimpleTableCell”,選中"Subclass of "里的“UITableViewCell”。
單擊“下一步”,保存的文件在SimpleTable項目文件夾,並單擊“創建”繼續。Xcode將在Project Navigator中創建兩個名為“SimpleTableCell.h”文件和“SimpleTableCell.m”。
正如前面提到的中,SimpleTableCell類作為自定義單元格的數據模型。在單元格中,我們有三個值是可變的:thumbnail image view(縮略圖圖像視圖),name label(名稱標簽)和time label(時間標簽)。在這個類里,我們將添加三個屬性來表示這些動態值。
打開“SimpleTableCell.h”和之前的“@end”行中添加以下屬性:
1
2 3 |
@property
(nonatomic, weak
)
IBOutlet UILabel
*nameLabel;
@property (nonatomic, weak ) IBOutlet UILabel *prepTimeLabel; @property (nonatomic, weak ) IBOutlet UIImageView *thumbnailImageView; |
Property(屬性)和Outlet(出口)
上面的代碼定義了三個以后要與在Interface Builder中的表格單元格視圖連接的實例變量。使用關鍵字“@property”在類中聲明屬性,格式為:
@property (attributes) type name;
參考上面的代碼,weak和nonatomic是attributes。UILabel和UIImageView是type,而“nameLabel”,“prepTimeLabel”和“thumbnailImageView”是name。
那么,IBOutlet是什么?你可以把IBOutlet想成一個指令。為了與表視圖單元格(即SimpleTableCell.xib)中的元素相關聯,我們使用關鍵字“IBOutlet”讓Interface Builder中知道,他們被允許連接。后來,你會看到如何使這些outlets和在Interface Builder中的對象之間的連接。
現在,打開“SimpleTableCell.m”,以下“@implementation SimpleTableCell”下面添加以下代碼:
1
2 3 |
@synthesize
nameLabel
=
_nameLabel;
@synthesize prepTimeLabel = _prepTimeLabel; @synthesize thumbnailImageView = _thumbnailImageView; |
建立連接
保存更改並選擇“SimpleTableCell.xib”回到Interface Builder中。現在我們可以在類的屬性和Label/ ImageView之間創建連接。
首先,選擇單元格,在“Identity Inspector”中把類改為“SimpleTableCell”,這樣就可以在單元格視圖和我們之前創建的類之間建立聯系。
現在,我們要建立的連接的屬性。右鍵單擊"Objects"下的“SimpleTableCell”,以顯示“Outlets”查詢器。單擊並按住“nameLabel”旁邊的圓圈,並將其拖動到Label – Name”對象。Xcode會自動建立連接。
為“prepTimeLabel”和“thumbnailImageView”重復上述操作:
View”:
- 連接“prepTimeLabel” 和“Label – Time”
- 連接“thumbnailImageView” 和“ImageView”
當你建立所有的連接后,它看起來應該是這樣的:
更新SimpleTableViewController
我們已經完成了自定義表格單元格的設計和編碼。最后,我們來到最后修改的部分 - 確認自定義單元格放在SimpleTableViewController中。
讓我們重溫在“SimpleTableView.m”的代碼:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
-
(UITableViewCell
*
)tableView
:
(UITableView
*
)tableView cellForRowAtIndexPath
:
(
NSIndexPath
*
)indexPath
{ static NSString *simpleTableIdentifier = @ "SimpleTableItem"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier :simpleTableIdentifier ]; if (cell == nil ) { cell = [ [UITableViewCell alloc ] initWithStyle :UITableViewCellStyleDefault reuseIdentifier :simpleTableIdentifier ]; } cell.textLabel.text = [tableData objectAtIndex :indexPath.row ]; cell.imageView.image = [UIImage imageNamed : [thumbnails objectAtIndex :indexPath.row ] ]; return cell; } |
我們先前使用默認的表視圖單元格(即UITableViewCell)顯示的表項。為了使用我們的自定義表格單元格,我們必須改變在“SimpleTableView.m”代碼:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
-
(UITableViewCell
*
)tableView
:
(UITableView
*
)tableView cellForRowAtIndexPath
:
(
NSIndexPath
*
)indexPath
{ static NSString *simpleTableIdentifier = @ "SimpleTableCell"; SimpleTableCell *cell = (SimpleTableCell * ) [tableView dequeueReusableCellWithIdentifier :simpleTableIdentifier ]; if (cell == nil ) { NSArray *nib = [ [ NSBundle mainBundle ] loadNibNamed : @ "SimpleTableCell" owner :self options : nil ]; cell = [nib objectAtIndex : 0 ]; } cell.nameLabel.text = [tableData objectAtIndex :indexPath.row ]; cell.thumbnailImageView.image = [UIImage imageNamed : [thumbnails objectAtIndex :indexPath.row ] ]; cell.prepTimeLabel.text = [prepTime objectAtIndex :indexPath.row ]; return cell; } |
然而,當你你更新代碼后,,Xcode檢測會有一些錯誤在源代碼編輯器。

源代碼的錯誤指示由Xcode
有什么問題嗎?我們剛剛修改的代碼告訴“SimpleTableViewController”去使用“SimpleTableCell”類的表格單元格。然而,“SimpleTableViewController”不知道“SimpleTableCell”類。這就是為什么Xcode會顯示錯誤。
正如在第一個教程說的,一個頭文件中聲明一個類的接口。對於“SimpleTableViewController”要認識“SimpleTableCell”,我們必須在“SimpleTableViewController.m”導入“SimpleTableCell.h”。

導入SimpleTableCell.h
通過導入“SimpleTableCell.h”,“SimpleTableViewController”知道"SimpleTableCell是什么並可以利用它。
最后,由於表格單元格的高度改為78,在“@end”前面添加下面的代碼。
1
2 3 4 |
-
(CGFloat
)tableView
:
(UITableView
*
)tableView heightForRowAtIndexPath
:
(
NSIndexPath
*
)indexPath
{ return 78; } |
現在,點擊“Run”按鈕和您的SimpleTable的應用程序看起來應該象下面這樣:
你的功課
您可能會注意到應用程序沒有顯示具體時間。我故意把這個給你。嘗試在你的代碼做一些修改來更新准備時間。你最終的應用程序看起來非常類似下面的:
下一個教程會有什么?
在完成本教程后,你應該對UITableView有一個更好的了解,你可以創建自己的表格單元格。下一步,我們將進一步討論如何處理行選擇。
與往常一樣,我喜歡聽聽您的意見。