具有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 }
最简单优雅的方式是
- 为webview添加高度布局约束
-
添加webview委托完成加载,然后将contentSize height设置为高度布局约束的常量。
-
保持tableview的实例或对主tableview进行委托 – 块 – 闭包。
- 调用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框架高度。