具有UIWebView动态高度的UITableViewCell

我有一个表格视图,其中包含webView的单元格,我希望单元格的高度与webView的高度相匹配。

这是我使用的代码:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("newsCell") as! NewsTableViewCell cell.webView.loadHTMLString("test
test
test
test
test
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() }

这就是结果: https : //postimg.cc/image/8qew1lqjj/

webView是正确的高度,但单元格不是,我该如何解决这个问题?

TableView将调整单元格本身,你只需要实现tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat委托方法。

是的,您最初不知道WebView的高度,但您可以计算它,然后让TableView重新加载单元格。 像这样的东西:

 class TableViewController: UITableViewController, UIWebViewDelegate { var content : [String] = ["test1
test1
test1
test1
test1
test1", "test22
test22
test22
test22
test22
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) } // ... }

这对我来说很简单,用动态加载WebView上的Html字符串。

首先使用scroll禁用TableViewCell中的textView,然后使用ContentView在所有4面上采用WebView,Apply Zero约束。 现在为textview和WebView赋予相同的高度约束。现在为两个视图提供相同的文本,如下面的代码所示。

对于Clean UI隐藏textView来自XIB或storyBoard。

 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 10 } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return UITableViewAutomaticDimension } func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { return 100 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewcell") as! tableviewcell let theString : String = "

Subheader

" let theAttributedString = try! NSAttributedString(data: theString.data(using: String.Encoding.utf8, allowLossyConversion: false)!,options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) cell.textview.attributedText = theAttributedString cell.webview.loadHTMLString(theString, baseURL: nil) return cell }

斯威夫特4

ifau的答案为Swift 4修改,使用UITableView而不是UITableViewController

在故事板中,使用UITableView 。 添加1个原型单元格。 将单元格的reuseIdentifier保持为“ cell ”。 将webView拖到单元格中,并将前导,尾随,顶部和底部约束设置为0.将单元格类设置为TableViewCell

TableViewCell.swift

将webViewsockets连接到故事板:

 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

将tableViewsockets连接到故事板:

 import UIKit class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIWebViewDelegate { @IBOutlet weak var tableView: UITableView! var content : [String] = ["test1
test1
test1", "test22
test22
test22
test22
test22
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) } }

计算webview的高度后使用DispatchQueue重新加载tableViewcell高度DispatchQueue.main.async它可以避免exception的空白空间并在重新加载webview框架时崩溃

 func webViewDidFinishLoad(_ webView: UIWebView) { var frame : CGRect = webVwModule.frame; frame.size.height = 1; self.webVwModule.frame.size = webVwModule.sizeThatFits(.zero) frame.size = self.webVwModule.frame.size; webView.frame = frame; webViewContentHeight = self.webVwModule.frame.size.height; isWebViewLoaded = true DispatchQueue.main.async(execute: { () -> Void in self.tableView.beginUpdates() self.tableView.endUpdates() }) } override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return webViewContentHeight! } 
 var heightOfWebview=0 func webViewDidFinishLoad(_ aWebView: UIWebView) { var frame: CGRect = aWebView.frame frame.size.height = 1 aWebView.frame = frame let fittingSize = aWebView.sizeThatFits(CGSize.zero) frame.size = fittingSize aWebView.frame = frame heightOfWebview = Int(fittingSize.height) tableView.beginUpdates() tableView.endUpdates() print("Calling webViewDidFinishLoad. Cell size value: \(heightOfWebview)") } override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return CGFloat(220+heightOfWebview) /// 220 is my static value } 

最好的方式对我有用。

 var heightOfWebview: CGFloat = 0 func webViewDidFinishLoad(_ aWebView: UIWebView) { var frame: CGRect = aWebView.frame frame.size.height = 1 aWebView.frame = frame let fittingSize = aWebView.sizeThatFits(CGSize.zero) frame.size = fittingSize aWebView.frame = frame heightOfWebview = Int(fittingSize.height) tableView.beginUpdates() tableView.endUpdates() print("Calling webViewDidFinishLoad. Cell size value: \(heightOfWebview)") } override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return heightOfWebview } 

最简单优雅的方式是

  1. 为webview添加高度布局约束
  2. 添加webview委托完成加载,然后将contentSize height设置为高度布局约束的常量。

  3. 保持tableview的实例或对主tableview进行委托 – 块 – 闭包。

  4. 调用tableview beginupdate endupdate让tableview知道他们应该validation布局。
 class WebViewTableViewCell: UITableViewCell { weak var viewController: ViewController? = nil @IBOutlet weak var webView: UIWebView! @IBOutlet weak var heightLayoutConstraint: NSLayoutConstraint! override func awakeFromNib() { super.awakeFromNib() webView.loadRequest(URLRequest(url: URL(string: "https://tinhte.vn")!)) webView.delegate = self webView.scrollView.isScrollEnabled = false // Initialization code } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) // Configure the view for the selected state } } extension WebViewTableViewCell: UIWebViewDelegate { func webViewDidFinishLoad(_ webView: UIWebView) { heightLayoutConstraint.constant = webView.scrollView.contentSize.height viewController?.tableView.beginUpdates() viewController?.tableView.endUpdates() } } 

我还有一个你应该考虑的解决方案。 创建一个高度约束并将其链接到您的UITableViewCell类。 然后实现委托方法func webViewDidFinishLoad(_ webView: UIWebView) ,并在调用它时将高度约束设置为等于webView.scrollView.contentSize.height

实现UITableview委托heightforrowatindexpath以返回webview框架高度。

Interesting Posts