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:
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
}
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)
}
// ...
}
After calculating the height of webview Use DispatchQueue for reloading the tableViewcell height DispatchQueue.main.async
.It avoids abnormal empty spaces and crash while reloading webview frame
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!
}
The most easy and elegant way is
Add webview Delegate finished loading then set contentSize height to constant of height layout constraint.
Keep instance of tableview or make a delegate - block - closure to main tableview.
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()
}
}
It's work for me, easy Way to load Html String on WebView with dynamic.
First take textView in TableViewCell with scroll disable and then take WebView, Apply Zero constraint on all 4 Side with ContentView. Now give same height constraint to both textview and WebView.Now give same text to both view as shown below code.
For Clean UI Hide textView From XIB or 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 = "</p><img src='https://pbs.twimg.com/profile_images/655066410087940096/QSUlrrlm.png' width=100 height=100 /><h2>Subheader</h2>"
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
}
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()
}
}