Self-sizing Table View Cells part I
Bài đăng này đã không được cập nhật trong 3 năm
Theo hướng dẫn từ: https://www.raywenderlich.com/129059/self-sizing-table-view-cells
Tutorial này được sử dụng trên Xcode 7.3, iOS9 và Swift 2.2.
Nếu bạn đã từng sử dụng custom tableViewCell, thì tức là bạn có thể đã từng dành khá nhiều thời gian cho sizing table view cells. Bạn có thể đã rất quen thuộc với việc tính toán thủ công chiều cao của cell thông qua chiều cao của mỗi label, imageView, textField,... trong cell. Thực sự, đến thời điểm hiện tại thì phương pháp này mất khá nhiều thời gian và rất dễ xảy ra lỗi trong tính toán. Trong tutorial này, bạn sẽ học cách để tạo ra tableViewCell mà tự động layout sao cho zice của nó fit với nội dung bên trong. Để đọc tutorial này, bạn cần phải quen thuộc với Auto Layout, UITableView và Swift development.
Getting Started
Trở lại những ngày tháng của iOS6, Apple đã giới thiệu 1 công nghệ tuyệt vời vào thời điểm đó: Auto Layout. Các developer hân hoan tột độ, các đảng phái hội nhóm về Auto Layout bắt đầu xuất hiện, các ban nhạc thi nhau viết bài và hát để kỷ niệm sự vĩ đại của Auto Layout...
Về bạn chất nó chỉ là việc kéo giãn (stretch) nhưng nó thực sự có vai trò lớn. Trong khi nó truyền cảm hứng cho các developer, Auto Layout vẫn còn rất rườm rà. Việc viết code manualy cho Auto Layout là 1 ví dụ rõ ràng cho điều này. Thời ban đầu ấy, Interface Builder vẫn còn khá kém hiệu quả khi thiết lập các rằng buộc.
Trở lại thời điểm bây giờ, Với tất cả sự cải tiến của Interface Builder và iOS 8, nó rất dễ dàng để sử dụng AutoLayout trong việc tạo ra self-sizing tableViewCell. Những gì bạn cần phải làm đó là:
- Sử dụng Auto Layout khi tạo tableViewCell
- đặt giá trị rowHeight của tableView thành UITableViewAutomaticDimension
- Set giá trị cho estimatedRowHeight hoặc implement the height estimation delegate method.
Tutorial App Overview
Hãy tưởng tượng khách hàng hàng đầu của bạn đến nói với bạn rằng:"Tôi muốn một app mà show ra các nghệ sĩ nổi tiếng nhất từng tồn tại, và 1 số tác phẩm nổi bật nhất của họ! Chúng tôi đã tạo ra app, nhưng chúng tôi đang băn khoăn trong việc display nội dung lên trên 1 tableView" "Bạn có thể khiến nó hoạt động?" Bạn sẽ cảm thấy sự thôi thúc bắt tay vào công việc ngay lập tức, trước hết hãy download the "client's code": https://cdn1.raywenderlich.com/wp-content/uploads/2016/05/Artistry-Starter.zip
Open file Main.storyBoard (trong Views group bên dưới Artistry project). bạn sẽ thấy 3 scenes:
Từ trái qua phải, chúng bao gồm:
- a top-level navigation controller
- ArtistListViewController show ra list các nghệ sĩ
- ArtistDetailViewController thể hiện các tác phẩm của 1 artist và thông tin về mỗi 1 tác phẩm đó.
Build&Run, bạn sẽ thấy list các nghệ sĩ trong ArtistListViewController. Chọn nghệ sĩ đầu tiên (Pablo Picasso) và app sẽ segue đến ArtistDetailViewController, mà display ra list các công việc, tác phẩm của ông:
Ta có thể thấy không chỉ thiếu sót các hình ảnh của mỗi nghệ sĩ và từng công trình, mà cả thông tin mà bạn đang cố gắng xem cũng bị cắt bớt. Mỗi phần của thông tin và image sẽ có kích thước khác nhau, vì vậy chúng ta không chỉ tăng chiều cao của cell là giải quyết được. Chiều cao của cell phải dynamic, dựa trên nội dung của từng cell. Chúng ta sẽ bắt đầu thực hiện trên ArtistListViewController.
Self-Sizing Table View Cells
Để có được dynamic cell height, bạn cần phải tạo ra 1 custom table view cell và set up nó với Auto Layout thật chính xác. Tạo mới 1 Cocoa Touch Class với tên ArtistTableViewCell và subclass của UITableViewCell. Open ArtistTableViewCell.swift, xoá hết những code tự gen của nó và thêm property sau:
@IBOutlet var bioLabel: UILabel!
Tiếp theo, open Main.storyboard, chọn cell ở bên trong table view của ArtistListViewController. Trong Identity Inspector, đổi Class của nó thành ArtistTableViewCell:
Kéo 1 UILabel vào trong cell, set text thành Bio. Set Property Lines của label thành 0 như sau:
Set số dòng của label trong việc dynamically sized cell là rất quan trọng. 1 label với number of lines được set thành 0 sẽ grow dựa trên số lượng text mà nó show. 1 label với number of line được set với 1 số khác 0 sẽ cắt cụt khi nó hết dòng. Kết nối outlet bioLabel của ArtistTableVIewCell với label trong cell:
Trick để Auto Layout làm việc trên UITableViewCell đó là đảm bảo được bạn có constraints để pin mỗi 1 subview trên tất cả các hướng của nó: tức là mỗi subview phải có leading, top, trailing và bottom constraints. Khi đó chiều cao nội tại (intrinsic height) của những subviews sẽ được dùng để tính ra chiều cao của cell.
Select bioLabel, nhấn vào nút Pin ở phía dưới của storyboard. Ở menu này, chỉ cần chọn 4 dòng đứt đoạn phía trên của menu, chỉnh leading và trailing thành 8, click Add Constraints:
Pin như trên sẽ đảm bảo rằng không cần biết cell sẽ to nhỏ ntn, như bio label sẽ luôn:
- 0 point top&bottom margins
- 8 points leading&trailing margins
Build&Run app, bạn sẽ thấy rằng... không có gì thay đổi cả. Bởi vì ta vẫn chưa:
Configure the Table View
Sửa method tableView(_:cellForRowAtIndexPath:) trong ArtistListViewController.swift như sau:
func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell",
forIndexPath: indexPath) as! ArtistTableViewCell
let artist = artists[indexPath.row]
cell.bioLabel.text = artist.bio
cell.bioLabel.textColor = UIColor(red: 114 / 255,
green: 114 / 255,
blue: 114 / 255,
alpha: 1.0)
return cell
}
Đoạn code phía trên khá là đơn giản: bạn dequeue 1 cell, set thông tin cho nó và text color rồi return cell. Run app 1 lần nữa, và bạn sẽ thấy... vẫn ko có gì thực sự thay đổi. Bạn bây giờ sử dụng bioLabel, nhưng nó vẫn chỉ show ra 1 line of text. Bởi vì bạn vẫn chưa set chiều cao của cell theo nội dung bên trong nó. Quay lại ArtistListViewController, và add thêm 2 dòng code sau vào method viewDidLoad():
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 140
Khi bạn set rowHeight của tableView thành UITableViewAutomaticDimension, table view sẽ hiểu rằng nó sẽ sử dụng AutoLayout constraint và nội dung bên trong của chính cell để tính toán chiều cao của mỗi cell. Để cho tableview làm điều này, bạn cũng PHẢI cung cấp 1 estimatedRowHeight. tring trường hợp này, 140.0 chỉ là 1 giá trị tuỳ tiện mà cso thể hoạt động được trong trường hợp cụ thể này. Vối project của riêng bạn, bạn nên chịn 1 giá trị mà được tính toán theo kiểu data của bạn mà bạn sẽ hiển thị thì tốt hơn. Build&Run, bạn sẽ thấy từng công việc của mỗi artist:
All rights reserved