Ở bài trước, chúng ta đã tạo một ứng dụng SimpleTable để hiển thị danh sách tên các món ăn với ảnh được định sẵn. Ở bài này chúng ta sẽ tiếp tục làm việc với ứng dụng đó nhưng sẽ khiến nó trở nên lung linh hơn.

  • Hiển thị các ảnh khác nhau cho các hàng khác nhau - lần trước chúng ta hiển thị cùng 1 ảnh cho tất cả các hàng. Thật không thể tốt hơn khi hiển thị từng ảnh cho từng món ăn phải không?
  • Tùy biến ô trong table view, thay vì sử dụng giao diện mặc định của table view cell, lần này chúng ta sẽ xây dựng giao diện cho riêng mình.

1. Hiển thị các ảnh thumbnail khác nhau:

Trước khi chúng ta thay đổi code, hãy nhìn lại một lần nữa code để hiển thị ảnh thumbnail trong table row.

Lần trước, chúng ta đã thêm dòng code để chỉ ra cho UITableView hiển thị ảnh có tên là "creme_brelee.jpg" trong từng hàng. Rõ ràng rằng chúng nên được hiển thị các ảnh khác nhau, do vậy chúng ta cần phải sửa lại code. Như giải thích từ trước, phương thức " cellForRowAtIndex" được gọi bởi iOS một cách tự động mỗi lần trước khi hàng trong bảng được hiển thị.

[code language="objc"]- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath[/code]

Nếu bạn nhìn vào tham số (parameter) của phương thức, nó được truyền vào tham số "indexPath" khi được triệu gọi. Tham số indexPath chứa đựng số hàng trong một bảng. Bạn có thể sử dụng thuộc tính (property) indexPath.row để tìm ra hàng hiện tại. Giống như mảng, hàng trong bảng được bắt đầu từ số 0. Hay nói cách khác, thuộc tính indexPath.row trả về (return) giá trị 0 cho hàng đầu tiên của bảng.

Vậy để hiển thị các ảnh thumbnail khác nhau, chúng ta cần một mảng (array) mới (có thể có tên là thumbnails) để lưu các tên ảnh thumbnail:

[code language="objc"]@implementation SimpleTableViewController
{
NSArray *recipes;
NSArray *thumbnails;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Khoi tao ten cac mon an
recipes= [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];
// Khoi tao ten cac anh thumbnail
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];
}[/code]

Như bạn có thể thấy đoạn code ở trên, chúng ta đã khởi tạo mảng thumbnails với danh sách tên các file ảnh. Thứ tự của các ảnh tương ứng với dữ liệu của mảng recipes.

Để giúp bạn thuận tiện hơn, bạn có thể tải về bộ ảnh có sẵn tại đây và add (thêm) nó vào project của bạn. Hãy nhớ đánh dấu vào ô "Copy items into destination group's folder".

Sau khi thêm các ảnh vảo project của bạn, bạn có thể thấy chúng xuất hiện trong phần Project Navigator giống như hình sau:

Sau đó, thay đổi dòng code trong phương thức "cellForRowAtIndex" thành:

[code language="objc"]cell.imageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];[/code]

[thumbnails objectAtIndex:indexPath.row] là gì?

Dòng code trên mục đích để lấy ra tên của các ảnh cho từng hàng nhất đinh. Có thể nói, đối với hàng thứ nhất, thuộc tính indexPath.row sẽ trả về giá trị bằng 0 và chúng ta sẽ lấy ra được tên ảnh là "egg_benedict.jpg" từ mảng thumbnails bằng cách sử dụng method (phương thức) "objectAtIndex".

Sau khi sửa đổi xong tất cả mọi thứ, hãy thử chạy ứng dụng của bạn lại 1 lần nữa. Nó sẽ hiển thị các ảnh thumbnail khác nhau cho từng hàng khác nhau:

2. Tùy biến Table View Cell (ô trong bảng):

Dường như ứng dụng bây giờ nhìn đẹp hơn phải không? Chúng ta sẽ làm nó đẹp hơn nữa bằng cách tùy biến ô trong bảng. Hơn hết chúng ta sẽ không sử dụng giao diện mặc định của table view cell nữa. Vị trí và kích thước của anh thumbnail đã được gán cố định. Vậy nếu chúng ta muốn ảnh thumbnail lớn hơn và hiển thị ra thời gian chuẩn bị của từng (preparation time) món ăn như hình sau thì sao?

3. Thiết kế Cell (ô):

Trong trường hợp này, bạn cần phải tạo và thiết kế cho riêng mình một table cell. Quay trở lại Xcode. Trong phần Project Navigator , click chuột phải vào thư mục " SimpleTable" và chọn "New File.."

Chúng ta sẽ tự thiết kế cho riêng mình một table cell, trước tiên chúng ta cần phải tạo một file Interface Builder cho cell (ô). Trong trường hợp này, chúng ta chỉ cần bắt đầu với một giao diện rỗng "Empty". Nhấn next để tiếp tục.

Khi hộp thoại xuất hiện để chọn dòng thiết bị, bạn chọn iPhone và nhấn next để tiếp tục. Lưu tên file là "SimpleTableCell".

Một khi file đã được tạo ra, bạn có thể nhìn thấy nó nằm trong phần Project Navigator. Chọn file "SimpleTableCell.xib" để chuyển sang phần xây dựng giao diện. Chúng ta sẽ thiết kế look and feel (cái này minh không dịch, bạn hiểu nó có ý nghĩa là giao diện) cho table cell.

Ở trong phần Object Library (góc dưới bên tay phải), chọn "Table View Cell" và kéo nó vào khu vực thiết kế của phần xây dựng giao diện (Interface Builder).

Để phù hợp với ảnh thumbnail lớn hơn, chúng ta cần phải thay đổi chiều cao của cell. Đơn giản là chỉ cần kéo dãn cell ra, cho đến khi Xcode ghi là H:78.0 tức là chiều cao là 78, và chiều rộng là 320.

Ngoài ra bạn cụng có thể sử dụng Thanh kích thước - Size Inspector để thay đổi chiều cao.

Tiếp đó, bạn chọn thanh thuộc tính - Attributes Inspector nằm trên cùng của phần tiện ích - Utility Area và đặt định danh - Identifier của cell tùy biến thành "SimpleTableCell". Định danh này sẽ được sử dụng sau.

Sau khi cấu hình table cell view, chúng ta sẽ thêm các phần tử vào trong đó. Chọn "Image View" và kéo nó vào Table View Cell.

Image View này sẽ được sử dụng để hiển thị ảnh thumbnail. Bạn có thể chỉnh sửa kích thước của nó để phù hợp với cell. Mình khuyên bạn đặt chiều cao (height) và chiều rộng (width) đều bằng 69 pixels.

Tiếp đó, chúng ta sẽ thêm vào 3 label (nhãn): Name - tên, Prep Time - Thời gian chuẩn bị, và Time - thời gian. Lable "Name" sẽ được sử dụng để hiển thị tên của món ăn. Lable "Prep Time" là label tĩnh (static) mà chỉ hiển thị dòng chữ "Prep Time". Cuối cùng là lable "Time" là label động (dynamic) sử dụng để hiển thị giá trị thời gian chuẩn bị từng món ăn khác nhau.

Để thêm 1 lable, bạn chọn "Label" trong phần Object library (thư viện đối tượng - góc phải phía dưới) và kéo nó vào cell. Bạn có thể nhấn đúp (double click) vào lable để sửa tên cho nó.

Bạn có thể nhận thấy kích thước font chữ và kiểu khác nhau cho từng label như ở hình trên. Để thay đổi kiểu font, bạn chọn vào Label và sau đó chọn thanh thuộc tính - " Attribute Inspector". Tại đó bạn có thể thay đổi kiểu font bằng cách chọn ở ô Font và bạn có thể đặt kích thước cho font. Bạn cũng có thể thay đổi màu sắc và vị trí của font tại đó.

Bản thiết kế cuối cùng của bạn sẽ giống như thế này:

4. Tạo 1 class (lớp) cho Cell tùy biến:

Trước đó chúng ta đã thiết kế xong table cell. Tuy nhiên làm cách nào mà chúng ta có thể thay đổi giá trị label của cell tùy biến? Chúng ta sẽ tạo một lớp mới cho table view cell tùy biến. Lớp này thể hiện cho tầng mô hình dữ liệu (data model) của cell tùy biến.

Cũng giống như trước, click chuột phải vào thư mục SimpleTable trong phần Project Navigator và chọn New/File...

Sau đó Xcode sẽ xuất hiện một hộp thoại để chọn template. Chúng ta đang tạo một lớp mới cho table view cell tùy biến, do vậy hãy chọn " Objective-C class" dưới mục "Cocoa Touch" và sau đó nhấn next để tiếp tục.

Điền tên class là "SimpleTableCell" và chọn "UITableViewCell" trong mục "Subclass of".

Nhấn next để tiếp tục, lưu file trong thư mục project SimpleTable và nhấn Create để tiếp tục. Xcode sẽ tạo ra 2 file với tên là SimpleTableCell.h SimpleTableCell.m trong phần Project Navigator (điều hướng project).

Như đã nói đến từ trước, class SimpleTableCell đóng vai trò là mô hình dữ liệu (data model) của cell tùy biến. Trong cell (ô), chúng ta có 3 giá trị có thể thay đổi đó là: khung chứa ảnh thumbnail, label tên, lable thời gian. Trong lớp này, chúng ta sẽ thêm vào 3 thuộc tính (property) thể hiện cho 3 giá trị động đó.

Mở file SimpleTableCell.h và thêm các thuộc tính sau vào trước dòng "@end":

[code language="objc"]@property (nonatomic, weak) IBOutlet UILabel *nameLabel;
@property (nonatomic, weak) IBOutlet UILabel *prepTimeLabel;
@property (nonatomic, weak) IBOutlet UIImageView *thumbnailImageView;[/code]

Property và Outlet

Những dòng code trên định nghĩa ra 3 biến thể hiện (iVar - instance variable) mà sau đó được liên kết với table view cell trong phần xây dựng giao diện - Interface Builder. Từ khóa " @property" được sử dụng để định nghĩa là một thuộc tính trong một lớp theo cú pháp sau:
@property (cacThuocTinh) kieuDuLieu tenThuocTinh;
Được đề cập ở dòng code trên, weaknonatomic là các thuộc tính của property. UILabel và UIImageView là các kiểu dữ liệu, trong khi "nameLabel", "prepTimeLabel" và "thumbnailImageView" là các tên của property.
Vậy còn IBOutlet là gì? Bạn có thể nghĩ rằng IBOutlet như một chỉ thị. Để liên kết các biến thể hiện - iVar với các phần tử trong Table View Cell chúng ta sử dụng từ khóa " IBOutlet" để giúp Interface Builder biết rằng chúng được phép tạo ra các liên kết. Chút nữa, chúng ta sẽ biết cách để tạo ra 1 liên kết giữa các outlet và các đối tượng nằm trong Interface Builder.

Bây giờ hãy mở file SimpleTableCell.m ra và thêm dòng code sau ngay dưới dòng lệnh "@implementation SimpleTableCell":

[code language="objc"]@synthesize nameLabel = _nameLabel;
@synthesize prepTimeLabel = _prepTimeLabel;
@synthesize thumbnailImageView = _thumbnailImageView;[/code]

Từ khóa @synthesize

Từ khóa "@synthesize" giúp trình biên dịch tự động tạo ra code cho phép truy cập các property mà chúng ta đã khai báo trước đó. Nếu bạn quên việc này, Xcode sẽ cảnh báo ngay:

Tuy nhiên đối với Xcode 4.4 trở đi bạn không cần phải sử dụng từ khóa này nữa.

5. Tạo các liên kết (connection):

Lưu tất cả sự thay đổi và mở file "SimpleTableCell.xib" để quay lại với bộ xây dựng giao diện - Interface Builder. Bây giờ chúng ta sẽ tạo ra các liên kết giữa các property (thuộc tính) của lớp và các label, ImageView mà chúng ta đã tạo trong Interface.

Đầu tiên, chọn cell và thay đổi class thành SimpleTabelCell trong thanh định danh - Identity Inspector. Sự liên kết giữa cell với class mà chúng ta vừa mới tạo ra.

Bây giờ chúng ta thiết lập các liên kết với các property. Click chuột phải vào "SimpleTableCell" nằm dưới mục "Objects" để hiển thị ra danh sách các Outlets. Nhấn chuột vào vòng tròn nằm ngay cạnh "nameLabel" và giữ chặt, rồi kéo nó sang đối tượng "Label - Name". Xcode sẽ tự động thiết lập kết nối.

Lặp lại quá trình trên với “prepTimeLabel” và“thumbnailImageView”:

  • Liên kết “prepTimeLabel” với “Label – Time
  • Liên kết“thumbnailImageView” với“ImageView

Sau khi bạn hoàn tất các liên kết, nó sẽ giống như sau:

6. Cập nhật SimpleTableViewController:

Chúng ta đã hoàn thành việc thiết kế vả code cho table cell tùy biến. Cuối cùng chúng ta sẽ thay đổi những thứ còn lại, để sử cell tùy biến trong SimpleTableViewController.

Hãy quay lại với file SimpleTableView.m mà đã từng tạo hàng cho bảng như sau:

[code language="objc"]- (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 = [recipes objectAtIndex:indexPath.row];
cell.imageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];
return cell;
}[/code]

Chúng ta đã sử dụng table view cell mặc định để hiện thị dữ liệu trong bảng. Để sử dụng cell tùy biến của chúng ta, chúng ta cần phải sử đổi một số code trong file SimpleTableView.m như sau:

[code language="objc"]- (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 = [recipes objectAtIndex:indexPath.row];
cell.thumbnailImageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];
cell.prepTimeLabel.text = [prepTime objectAtIndex:indexPath.row];
return cell;
}[/code]

Tuy nhiên, sau khi bạn sửa đổi code của bạn, Xcode phát hiện ra một vài lỗi được chỉ ra trong trình soạn code.

Liệu có gì sai chăng? Code mà chúng ta vừa thay đổi đã chỉ cho SimpleTableViewController sử dụng class SimpleTableCell như là cell của table. Tuy nhiên, "SimpleTableViewController" dường như không nhận ra được. Đó là lý do tại sao Xcode báo lỗi.

Như đã giải thích từ bài hướng dẫn đầu tiên, file header định nghĩa ra interface của class. Để SimpleTableViewController hiểu được SimpleTableCell, chúng ta cần phải import (nhập) file SimpleTableCell.h vào trong file SimpleTableViewController.m

Bằng cách import file SimpleTableCell.h , file SimpleTableViewController biết đó là gì và có thể sử dụng nó được.

Cuối cùng, chiều cao của table cell thay đổi thành 78, thêm dòng code sau vào trước dòng "@end"

[code language="objc"]- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 78;
}[/code]

Bây giờ hãy nhấn nút Run để chạy ứng dụng SimpleTable. Nó sẽ có dạng như sau:

7. Bài tập dành cho bạn:

Bạn nên lưu ý rằng ứng dụng hiện tại mới chỉ hiện thị được giá trị Time cho label Prep Time. Phần thay đổi giá trị thời gian của nhãn Prep Time cho từng món ăn khác nhau đó sẽ là bài tập của bạn. Hãy thử thay đổi một vài dòng code và cập nhập lại thời gian chuẩn bị cho từng món ăn. Sau khi làm xong, ứng dụng của bạn sẽ giống như sau:

8. Kết:

Sau khi kết thúc bài hướng dẫn này, mình hy vọng bạn đã có cái nhìn khái quát hơn về UITableView và biết cách tạo ra table cell cho riêng mình. Bạn có thể download mã nguồn code ứng dụng của bài này tại link sau: Tải về . Chúc các bạn học tốt :D

Note: Bản gốc được viết từ website appcoda.com và được dịch bởi VietDevelopers. Mọi trích dẫn, hay copy vui lòng ghi rõ nguồn và được sự đồng ý của tác giả. Xin cảm ơn và chúc các bạn học tốt!

Lập trình iOS - Lập trình iOS cơ bản - Lập trình Swift - Lập trình Swift 3 - Học lập trình iOS - Lập trình di động - Học lập trình - Vietdevelopers - Vietdevelopers.com