Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UITableViewCell With UIWebView Dynamic Height

Tags:

I have a table view with cells that have a webView in them, I want the height of the cell to match the height of the webView.

This is the code I use:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {      let cell = tableView.dequeueReusableCellWithIdentifier("newsCell") as! NewsTableViewCell      cell.webView.loadHTMLString("test<br>test<br>test<br>test<br>test<br>test", baseURL: nil)     cell.webView.delegate = self      var webFrame = cell.webView.frame     var cellFrame = cell.frame     cell.frame = CGRectMake(cellFrame.origin.x, cellFrame.origin.y, cellFrame.width, webFrame.height + 20)     cell.backgroundColor = UIColor.redColor()      return cell }  func webViewDidFinishLoad(webView: UIWebView) {     println("finished loading")     var frame = webView.frame     frame.size.height = 1     webView.frame = frame      var fittingSize = webView.sizeThatFits(CGSizeZero)     frame.size = fittingSize     webView.frame = frame      var height: CGFloat = frame.height     println(height)      webView.frame = CGRectMake(frame.origin.x, frame.origin.x, frame.size.width, frame.size.height)      newsTable.beginUpdates()     newsTable.endUpdates() }     

And this is the result: https://postimg.cc/image/8qew1lqjj/

The webView is the correct height but the cell isn't, How can I fix this problem?

like image 827
OmerN Avatar asked Sep 13 '15 10:09

OmerN


2 Answers

TableView will resize cells itself, you just need implement tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat delegate method.

Yes, you don't know the height of WebView initially, but you can calculate it and then ask TableView to reload cell. Something like this:

class TableViewController: UITableViewController, UIWebViewDelegate {     var content : [String] = ["test1<br>test1<br>test1<br>test1<br>test1<br>test1", "test22<br>test22<br>test22<br>test22<br>test22<br>test22"]     var contentHeights : [CGFloat] = [0.0, 0.0]      // ...      override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell     {         let cell = tableView.dequeueReusableCellWithIdentifier("newsCell", forIndexPath: indexPath) as! NewsTableViewCell         let htmlString = content[indexPath.row]         let htmlHeight = contentHeights[indexPath.row]          cell.webView.tag = indexPath.row         cell.webView.delegate = self         cell.webView.loadHTMLString(htmlString, baseURL: nil)         cell.webView.frame = CGRectMake(0, 0, cell.frame.size.width, htmlHeight)          return cell     }      override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat     {         return contentHeights[indexPath.row]     }      func webViewDidFinishLoad(webView: UIWebView)     {         if (contentHeights[webView.tag] != 0.0)         {             // we already know height, no need to reload cell             return         }          contentHeights[webView.tag] = webView.scrollView.contentSize.height         tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: webView.tag, inSection: 0)], withRowAnimation: .Automatic)     }      // ... } 
like image 137
ifau Avatar answered Oct 30 '22 12:10

ifau


Swift 4

ifau's Answer modified for Swift 4, using UITableView instead of UITableViewController.

In storyboard, take a UITableView. Add 1 prototype cell to it. Keep the reuseIdentifier of the cell to "cell". Drag a webView into the cell and set leading, trailing, top and bottom constraints to 0. Set the cell class to TableViewCell

TableViewCell.swift

Connect webView outlet to storyboard:

import UIKit  class TableViewCell: UITableViewCell {      @IBOutlet weak var webView: UIWebView!      override func awakeFromNib() {         super.awakeFromNib()         // Initialization code     }      override func setSelected(_ selected: Bool, animated: Bool) {         super.setSelected(selected, animated: animated)          // Configure the view for the selected state     }  } 

ViewController.swift

Connect the tableView outlet to the storyboard:

import UIKit  class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIWebViewDelegate {      @IBOutlet weak var tableView: UITableView!      var content : [String] = ["test1<br>test1<br>test1", "test22<br>test22<br>test22<br>test22<br>test22<br>test22"]      var contentHeights : [CGFloat] = [0.0, 0.0]      override func viewDidLoad() {         super.viewDidLoad()         // Do any additional setup after loading the view, typically from a nib.         tableView.dataSource = self         tableView.delegate = self     }      public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{         return content.count     }      public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{         let cell : TableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell          let htmlString = content[indexPath.row]         let htmlHeight = contentHeights[indexPath.row]          cell.webView.tag = indexPath.row         cell.webView.delegate = self         cell.webView.loadHTMLString(htmlString, baseURL: nil)         cell.webView.frame = CGRect(x: 0, y: 0, width: cell.frame.size.width, height: htmlHeight)          return cell     }      func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {         if contentHeights[indexPath.row] != 0 {             return contentHeights[indexPath.row]         }     }      public func webViewDidFinishLoad(_ webView: UIWebView){         if (contentHeights[webView.tag] != 0.0)         {             // we already know height, no need to reload cell             return         }          contentHeights[webView.tag] = webView.scrollView.contentSize.height         tableView.reloadRows(at: [IndexPath(row: webView.tag, section: 0)], with: .automatic)     } } 
like image 45
Dia Avatar answered Oct 30 '22 12:10

Dia