原文發表在個人我的網站:Auto Layout 使用心得(五)—— 根據文字、圖片自動計算 UITableViewCell 高度html
此係列文章代碼倉庫在 https://github.com/johnlui/AutoLayout ,有不明白的地方能夠參考個人 Auto Layout 設置哦,下載到本地打開就能夠了。ios
本文中,咱們將一塊兒使用 Auto Layout 技術,讓 UITableViewCell 的高度隨其內部的 UILabel 和 UIImageView 的內容自動變化。git
放置一個按鈕,恢復到 firstTableViewController 的鏈接:github
別忘了添加約束讓他居中哦。swift
將 firstTableViewCell 的尺寸設置爲 600 * 81,將 logo 的尺寸設置爲 80 * 80。將 logo 的約束脩改成以下圖所示:app
修改 label 的尺寸和位置,添加約束以下圖:ide
爲了便於返回。操做以下圖:性能
選中 label,設置 lines 行數爲 0,表示不限長度自動折行:動畫
修改 label 的文字內容讓其超出一行:網站
swiftimport UIKit class firstTableViewController: UITableViewController { var labelArray = Array<String>() // 用於存儲 label 文字內容 override func viewDidLoad() { super.viewDidLoad() var nib = UINib(nibName: "firstTableViewCell", bundle: nil) self.tableView.registerNib(nib, forCellReuseIdentifier: "firstTableViewCell") // 循環生成 label 文字內容 for i in 1...10 { var text = "" for j in 1...i { text += "Auto Layout" } labelArray.append(text) } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } // MARK: - Table view data source override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return 50 } override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return labelArray.count } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("firstTableViewCell", forIndexPath: indexPath) as! firstTableViewCell cell.firstLabel.text = labelArray[indexPath.row] return cell } }
estimatedHeightForRowAtIndexPath 是 iOS 7 推出的新 API。若是列表行數有一萬行,那麼 heightForRowAtIndexPath 就會在列表顯示以前計算一萬次,而 estimatedHeightForRowAtIndexPath 只會計算當前屏幕中顯示着的幾行,會大大提升數據量很大時候的性能。
swiftclass firstTableViewController: UITableViewController { var labelArray = Array<String>() // 用於存儲 label 文字內容 var prototypeCell: firstTableViewCell! override func viewDidLoad() { super.viewDidLoad() var nib = UINib(nibName: "firstTableViewCell", bundle: nil) self.tableView.registerNib(nib, forCellReuseIdentifier: "firstTableViewCell") // 初始化 prototypeCell 以便複用 prototypeCell = tableView.dequeueReusableCellWithIdentifier("firstTableViewCell") as! firstTableViewCell ......
swiftoverride func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { let cell = prototypeCell cell.firstLabel.text = labelArray[indexPath.row] return cell.contentView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize).height + 1 }
上面讓 firstTableViewCell 根據 label 自動計算高度的過程當中,有一個超級大坑:若是給左側 UIImageView 賦的圖片較大(大於 80px),將看到以下奇怪的結果:
首先,把圖片的渲染模式改爲 Aspect Fit:
給 Images.xcassets 增長三張圖片,命名爲 0、一、2,尺寸從小到大:
給 cellForRowAtIndexPath 增長代碼:
swiftif indexPath.row < 3 { cell.logoImageView.image = UIImage(named: indexPath.row.description) }
查看效果:
新建一個 Group(虛擬文件夾),叫 Extensions,並在其內部新建 UIImage.swift 文件,內容以下:
swiftimport UIKit extension UIImage { func resizeToSize(size: CGSize) -> UIImage { UIGraphicsBeginImageContext(size) self.drawInRect(CGRectMake(0, 0, size.width, size.height)) let newImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return newImage } }
給 UIImage 類擴展了一個名爲 resizeToSize 的方法,返回一個按照要求的大小重繪過的 UIImage 對象。修改 cellForRowAtIndexPath 的代碼爲:
swiftoverride func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("firstTableViewCell", forIndexPath: indexPath) as! firstTableViewCell cell.firstLabel.text = labelArray[indexPath.row] if indexPath.row < 3 { var image = UIImage(named: indexPath.row.description)! if image.size.width > 80 { image = image.resizeToSize(CGSizeMake(80, image.size.height * (80 / image.size.width))) } cell.logoImageView.image = image } return cell }
搞定!
從上圖能夠看出,cell 已經能夠根據圖片和文字中比較高的一個徹底自適應。
感謝 《動態計算UITableViewCell高度詳解》,給我提供了許多基礎知識和靈感。