ios 具有 UIWebView 动态高度的 UITableViewCell
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32548771/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UITableViewCell With UIWebView Dynamic Height
提问by OmerN
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.
我有一个表格视图,其中包含一个 webView 的单元格,我希望单元格的高度与 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/
这就是结果:https: //postimg.cc/image/8qew1lqjj/
The webView is the correct height but the cell isn't, How can I fix this problem?
webView 是正确的高度,但单元格不是,我该如何解决这个问题?
回答by ifau
TableView will resize cells itself, you just need implement tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
delegate method.
TableView 会自行调整单元格的大小,您只需要实现tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
委托方法。
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:
是的,您最初不知道 WebView 的高度,但您可以计算它,然后让 TableView 重新加载单元格。像这样的东西:
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)
}
// ...
}
回答by Ujesh
It's work for me, easy Way to load Html String on WebView with dynamic.
它对我有用,在 WebView 上动态加载 Html 字符串的简单方法。
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.
首先在禁用滚动的 TableViewCell 中获取 textView,然后获取 WebView,使用 ContentView 在所有 4 个边上应用零约束。现在为 textview 和 WebView 提供相同的高度约束。现在为两个视图提供相同的文本,如下代码所示。
For Clean UI Hide textView From XIB or storyBoard.
对于干净的 UI 隐藏来自 XIB 或 storyBoard 的 textView。
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
}
回答by Dia
Swift 4
斯威夫特 4
ifau'sAnswer modified for Swift 4, using UITableView
instead of UITableViewController
.
ifau 的答案针对 Swift 4 进行了修改,使用UITableView
代替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
在故事板中,取一个UITableView
. 向其中添加 1 个原型单元格。保持单元格的重用标识符为“ cell
”。将 awebView
拖入单元格并将前导、尾随、顶部和底部约束设置为 0。将单元格类设置为TableViewCell
TableViewCell.swift
TableViewCell.swift
Connect webView outlet to storyboard:
将 webView 插座连接到故事板:
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
视图控制器.swift
Connect the tableView outlet to the storyboard:
将 tableView 插座连接到故事板:
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)
}
}
回答by Sheereen S
After calculating the height of webview Use DispatchQueuefor reloading the tableViewcell height DispatchQueue.main.async
.It avoids abnormal empty spaces and crash while reloading webview frame
计算完webview的高度后,使用DispatchQueue重新加载tableViewcell高度DispatchQueue.main.async
,避免在重新加载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!
}
回答by BatyrCan
The best way worked for me.
最好的方法对我有用。
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
}
回答by Trung Phan
The most easy and elegant way is
最简单优雅的方法是
- Add height layout constraint for webview
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.
- Call tableview beginupdate endupdate to let tableview know they should validate layout.
- 为 webview 添加高度布局约束
添加 webview Delegate 完成加载然后将 contentSize 高度设置为高度布局约束的常量。
保留 tableview 的实例或对主 tableview 进行委托 - 阻止 - 关闭。
- 调用 tableview beginupdate endupdate 让 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()
}
}
回答by Enrico Susatyo
I have one more solution that you should consider. Make a height constraint and link it to your UITableViewCell
class. Then implement the delegate method func webViewDidFinishLoad(_ webView: UIWebView)
, and when it is called set the height constraint to be equal to webView.scrollView.contentSize.height
.
我还有一个您应该考虑的解决方案。进行高度约束并将其链接到您的UITableViewCell
班级。然后实现委托方法func webViewDidFinishLoad(_ webView: UIWebView)
,并在调用时将高度约束设置为等于webView.scrollView.contentSize.height
。
回答by Nitin
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()
}
}
回答by Iya
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
}
回答by Martin Josephson
Implement the UITableview delegate heightforrowatindexpath to return the webview frame height.
实现 UITableview 委托 heightforrowatindexpath 以返回 webview 框架高度。