在可变高度 TableViewCell 内根据动态本地内容确定 UIWebView 高度
Posted
技术标签:
【中文标题】在可变高度 TableViewCell 内根据动态本地内容确定 UIWebView 高度【英文标题】:Determine UIWebView height based on dynamic local content, within a variable height TableViewCell 【发布时间】:2013-05-24 18:58:22 【问题描述】:好的,所以我知道这个问题已经被问过了。有很多好的建议,但我无法按预期工作。我正在尝试创建一个 tableview 单元格,它可以根据不同的 html 动态设置其加载高度。大家的建议是使用下面的方法。
-(void)webViewDidFinishLoad:(UIWebView *)webView
他们说要使用 javascript 计算高度,如下所示:
NSString *output = [webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"];
或者做这样的事情(我创造了这个):
self.webView = webView;
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView.frame = frame;
这两种方法都返回了 webview 的正确高度,但是它们发生在 tableview 初始化之后。这个 webViewDidFinishLoad 在 heightForRowAtIndexPath 方法之后被调用。因此,在构建表格时,我没有单元格的高度。所以然后每个人都说好,然后在你的 webViewDidFinishLoad 中重新加载一个 tableview ,它再次起作用,但我不喜欢这样,因为有一个滞后,当你到达那部分时,它会使 tableview 的滚动不稳定。我怎样才能解决这个问题?并使其顺利?我在想也许在加载视图之前以某种方式确定 webview 的高度,但不知道我会怎么做。还尝试将 html 转换为纯文本字符串,但这会导致错误高度,因为 html 有空格和内容,而纯文本没有。任何帮助将不胜感激!
【问题讨论】:
您能否尽早将 Web 视图加载到屏幕外,以便在调用 heightForRowAtIndexPath 之前完成它?另外,您是否确定了滞后和波动的性质?也许这个问题可以解决。 好主意!这就是我最终要做的。 【参考方案1】:我的建议与@Timothy Moose 非常相似,将webview 渲染到屏幕外。
我会在这里采取的方法是......
-(void)viewDidLoad
//Create a UIWebView and store it in a property
//Hook the delegate to the view controller.
//Load the html string to the UIWebView.
//The rest of your initialization
在这种情况下,您的heightForRowAtIndexPath:
仍可能会在网络视图完成之前被调用。
您可以通过多种方式来处理它。这是一个建议。
在 UIWebView 的 webViewDidFinishLoading
的委托方法中,检查以确保进行调用的 webview 是存储在您的属性中的 webview。如果是这样,请调用以重新加载包含您的 webview 的部分(或行)。这应该调用 heightForRowAtIndexPath:
方法再次调用,在这种情况下,您可以将 webview 的高度存储在 webViewDidFinishLoading
回调。
如果第一次显示视图时单元格不在屏幕上,则在cellForRowAtIndexPath:
中创建的单元格应该具有您在viewDidLoad
中创建的UIWebView
。通过将UIWebView
添加到单元格的内容视图来执行此操作。
如果第一次显示视图时单元格在屏幕上,我建议在第一次加载单元格时使用活动微调器,然后在 webview 加载完成后,使用 webview 重新加载单元格。
【讨论】:
很好的答案!这似乎是唯一有效的解决方案。将 webView 加载到屏幕外,然后存储高度非常完美。我遇到的唯一问题是在 cellForRowAtIndex 方法期间将 webview 添加回单元格。【参考方案2】:归根结底,在加载之前,您无法知道 webview 内容的高度。如果同样的代码设置表格和加载 webview,webview 总是会在表格显示后完成它的加载。
如果您重复加载相同的 HTML,您可以缓存高度,但第一次仍然会遇到问题。
因此,您要能够显示滚动 tableview 而不会出现断断续续的唯一方法是在 webview 加载之前拥有默认的单元格高度。然后改变它。但是你已经尝试过了,使用reload
。那是波涛汹涌的。
但是,单元格高度在默认高度和真实高度之间进行动画处理呢?也许这样会更容易接受。
如果您只更改高度,我相信您可以这样做而不是重新加载,以便为调整大小设置动画。
[tableView beginUpdates];
[tableView endUpdates];
这两行之间不需要任何东西。
也许您可以将此与缓存 HTML 的真实高度相结合,以便下次用户将其滚动到视图中。
【讨论】:
完美!!刚刚好。干杯!【参考方案3】:在您的情况下,您在 tableviewcell 中有 webview,因此在 heightForRowAtIndexPath 中将单元格的高度设置为 NSAttributedString 大小的高度,如下所示。
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
NSAttributedString *attributedText = [NSString getHTMLAttributedString:@"HTML Content"];
CGSize size = CGSizeMake(300, CGFLOAT_MAX);
CGRect paragraphRect = [attributedText boundingRectWithSize:size
options:(NSStringDrawingUsesLineFragmentOrigin)
context:nil];
return paragraphRect.size.height;
+(NSAttributedString *) getHTMLAttributedString:(NSString *) string
NSError *errorFees=nil;
NSString *sourceFees = [NSString stringWithFormat:
@"<span style=\"font-family: 'Roboto-Light';font-size: 14px\">%@</span>",string];
NSMutableAttributedString* strFees = [[NSMutableAttributedString alloc] initWithData:[sourceFees dataUsingEncoding:NSUTF8StringEncoding]
options:@NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]
documentAttributes:nil error:&errorFees];
return strFees;
【讨论】:
以上是关于在可变高度 TableViewCell 内根据动态本地内容确定 UIWebView 高度的主要内容,如果未能解决你的问题,请参考以下文章
自定义 tableviewcell 动态高度未根据约束更新(以编程方式自动布局)
iOS7根据从API下载的图像高度动态调整TableViewCell的高度
使用 Autolayout 自定义具有动态高度和全宽图像的 TableViewCell
IOS Swift 5 为动态高度 TableView 单元添加自定义 TableViewCell 分隔符