我想实现一个看起来像这样的方法:
setCellHeightForIndexPath(someIndexPath, 80)
然后该索引路径的表格视图单元格突然高度为80。
我想这样做的原因是因为我希望在完成加载HTML后,将单元格的高度设置为Web视图内容的高度。由于我只能在完成加载后获取网页视图的内容大小,因此我不能立即设置单元格高度。
有关详细信息,请参阅此question。
因此,在webViewDidFinishLoad
方法中,我可以获取Web视图的内容高度,将Web视图的高度设置为该高度,并调用此方法来设置单元格的高度。
看起来细胞高度只能在调用heightForRowAtIndexPath
时改变。我认为该方法将使用与my answer to this question类似的方法。我想我需要存储一系列高度?我只是想不出一种实现这个的方法!
我该如何实现这样的方法?
注意:不要告诉我这是不可能的。在Instagram应用程序中,我可以看到具有不同高度的不同图像完美地适合表格视图单元格。这些图像与我的网络视图类似。他们都需要时间来加载。
编辑:
让我展示一下我的一些尝试:
var results: [Entry] = []
var cellHeights: [CGFloat] = []
var webViews: [UIWebView] = []
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return results.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("resultCell")
let webView = cell!.contentView.viewWithTag(1) as! UIWebView
webView.loadHTMLString(results[indexPath.row].htmlDescriptionForSearchMode(.TitleOnly), baseURL: nil)
webView.delegate = self
webView.scrollView.scrollEnabled = false
webViews.append(webView)
cellHeights.append(400)
webView.stringByEvaluatingJavaScriptFromString("highlightSearch(\"day\")")
return cell!
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return indexPath.row < cellHeights.count ? cellHeights[indexPath.row] : 400
}
func webViewDidFinishLoad(webView: UIWebView) {
let height = CGFloat(webView.stringByEvaluatingJavaScriptFromString("document.height")!.toFloat()!)
webView.frame = CGRect(origin: webView.frame.origin, size: CGSizeMake(webView.frame.width, height))
print(height)
if let index = webViews.indexesOf(webView).first {
cellHeights[index] = height
tableView.beginUpdates()
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: index, inSection: 0)], withRowAnimation: .None)
tableView.endUpdates()
}
}
results
是我想要在网络视图中显示的内容。 cellHeights
用于存储每个单元格的高度。我将所有网络视图都放入webViews
数组中,以便我可以在indexOf
中调用webViewDidFinishLoad
来确定加载了哪个网络视图。
编辑:
所以我在我的表视图控制器中编写了这段代码,并参考了Andre的答案:
class SearchResultsController: UITableViewController, UIWebViewDelegate {
var entries: [Entry] = []
lazy var results: [Result] = {
return self.entries.map { Result(entry: $0) }
}()
var cellHeights: [CGFloat] = []
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return results.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let result = results[indexPath.section]
var cell = result.cell
if cell == nil {
print("cellForRow called")
cell = tableView.dequeueReusableCellWithIdentifier("resultCell") as! ResultCell
cell.webView.delegate = self
print(cell == nil)
print("loading \(result.entry.title)...")
cell.webView.loadHTMLString(result.entry.htmlDescriptionForSearchMode(.TitleOnly), baseURL: nil)
result.cell = cell
}
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return indexPath.row < cellHeights.count ? cellHeights[indexPath.row] : 400
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 169
tableView.rowHeight = UITableViewAutomaticDimension
tableView.tableFooterView = UIView()
}
func webViewDidFinishLoad(webView: UIWebView) {
print("didFinishLoad called")
if webView.loading {
return
}
guard let cell = webView.superview?.superview as? ResultCell else {
print("could not get cell")
return
}
guard let index = results.map({$0.cell}).indexOf(cell) else {
print("could not get index")
return
}
let result = results[index]
print("finished loading \(result.entry.title)...")
guard let heightString = webView.stringByEvaluatingJavaScriptFromString("document.height") else {
print("could not get heightString")
return
}
guard let contentHeight = Float(heightString) else {
print("could not convert heightString")
return
}
cell.webViewHeightConstraint.constant = CGFloat(contentHeight)
tableView.beginUpdates()
tableView.endUpdates()
}
}
class ResultCell: UITableViewCell {
@IBOutlet weak var webView: UIWebView!
@IBOutlet weak var webViewHeightConstraint: NSLayoutConstraint!
}
class Result {
let entry: Entry
var contentHeight: Float?
var cell: ResultCell!
init(entry: Entry) {
self.entry = entry
}
}
答案 0 :(得分:2)
你不能推动&#34;将新单元格高度放到表格视图上。相反,你需要制作表格视图&#34; pull&#34;来自heightForRowAtIndexPath
的新高度,并准备好提供新的高度。
当行r
的单元格加载完成时,您需要更新模型,使其知道行r
的新高度。之后,您需要告诉您的表视图重新加载自己,如下所示:
tableView.beginUpdates()
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.None)
tableView.endUpdates()
这将开始更新您的单元格的过程。 heightForRowAtIndexPath
将被调用。您的代码将返回新的高度。之后将调用cellForRowAtIndexPath
。您的代码应准备好返回已完成加载的单元格,而不会启动新的数据加载。
答案 1 :(得分:1)
我尝试使用自动自动布局和自动单元格高度计算来实现它。
也许有助于指出正确的方向: https://github.com/andreslotta/WebViewCellHeight
只是摘录:
func webViewDidFinishLoad(webView: UIWebView) {
if webView.loading {
return
}
guard let cell = webView.superview?.superview as? WebViewCell else {
print("could not get cell")
return
}
guard let index = websites.map({$0.cell}).indexOf(cell) else {
print("could not get index")
return
}
// get website
let website = websites[index]
print("finished loading \(website.urlString)...")
// get contentheight from webview
guard let heightString = webView.stringByEvaluatingJavaScriptFromString("document.height") else {
print("could not get heightString")
return
}
guard let contentHeight = Float(heightString) else {
print("could not convert heightString")
return
}
cell.webViewHeightConstraint.constant = CGFloat(contentHeight)
tableView.beginUpdates()
tableView.endUpdates()
}
答案 2 :(得分:0)
您可以像这样实施
将一个全局CGFloat用于高度和一个索引路径 现在当你需要更改高度时设置两个值并使用
[self.yourTableview beginUpdate]
[self.yourTableview endUpdate]
将更新您的手机
并且在cellForRowAtIndexPath
中你应该使用dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)
来确保你每次都有更新的单元格
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath == yourIndexpath) {
return gloablVariable;
} else {
return defauleHeight
}
}
希望有所帮助