如何在可变高度UITableView内基于内容确定UIWebView高度?


71

我正在尝试创建一个UITableView高度可变的行,如此问题的答案中所述

我的问题是每个单元格包含一个UIWebView具有不同(静态加载)内容的内容,我无法弄清楚如何根据该内容计算适当的高度。有没有办法做到这一点?我已经尝试过像这样的事情:

   (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
       WebViewCell *cell = (WebViewCell*)[self tableView:tableView cellForRowAtIndexPath:indexPath];
       [cell setNeedsLayout];
       [cell layoutIfNeeded];
       return cell.bounds.size.height;
    }

单元格本身是从笔尖加载的,而笔尖只是一个UITableViewCell包含的UIWebView。(如果单元格只是将自身调整为最大的html内容,那也很好,尽管可变高度会更好)。


您是否曾经知道过该怎么做?下面的答案似乎可以帮助您提高身高,但要等到您需要时再进行。您如何计算heightForRowAtIndexPath的高度,是否必须依靠webViewDidFinishLoad中的回调(webview委托)调用?
pbx 2012年

嗨,您好,最后您如何确定网络视图的高度,我也遇到了同样的问题……
Nik

有人有解决方案吗???仍然无法弄清楚这一点..
mikemike396

Answers:


77

这段代码对于使用表视图可能太慢了,但是可以解决这个问题。看起来没有其他选择,因为UIWebView不提供对DOM的直接访问。

在视图控制器中,viewDidLoad我在Web视图中加载了一些HTML,加载完成后,运行一些javascript以返回元素高度。

- (void)viewDidLoad
{
    [super viewDidLoad];
    webview.delegate = self;
    [webview loadHTMLString:@"<div id='foo' style='background: red'>The quick brown fox jumped over the lazy dog.</div>" baseURL:nil];
}

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    NSString *output = [webview stringByEvaluatingJavaScriptFromString:@"document.getElementById(\"foo\").offsetHeight;"];
    NSLog(@"height: %@", output);
}

听起来可以使它工作,但是我已经在表视图中尝试过了,它返回了一个空字符串(我想是因为Web视图尚未完成加载)。我想我可以使用屏幕外的Webview对此进行预先计算,并为tableview缓存结果。
frankodwyer

您是否正在测量webViewDidFinishLoad中的高度?这是代表回调,表明加载已完成。它不应返回空字符串。
duncanwilcox

37
我改用了:NSString * output = [webView stringByEvaluatingJavaScriptFromString:@“ document.body.scrollHeight;”];
BadPirate

3
使用iOS 4.3,我必须执行以下操作:为我的webView设置一个很小的高度(即1px),并执行BadPirate建议的调用,然后再调整滚动视图的内容值和Web视图的帧值。
肮脏的亨利

2
您必须将初始UIWebView的高度至少设置为1px,否则在进行JS调用时,您将获得返回的屏幕高度。
Vadoff

28

我很高兴找到您的答案,JavaScript技巧对我来说效果很好。

但是,我想说的还有“ sizeThatFits:”方法:

CGSize goodSize = [webView sizeThatFits:CGSizeMake(anyWidth,anyHeigth)];

我们必须将首选大小设置为零,但除此之外,它通常总是有效的!

通常,因为使用UIWebViews,它似乎仅在第二次加载时起作用(我使用“ loadHTMLString:”方法,是的,我从委托“ didFinishLoad:”方法中调用“ sizeThatFits:”)。

因此,这就是为什么我很高兴找到您的解决方案在任何情况下都有效的原因。


@Shade:请参阅我的答案,如何在较新的iOS版本上实现此目的。
2011年

请谨慎回答!有时返回错误height!当与许多图像一起使用时,我得到了错误的价值
Andrey Gordeev

6

这似乎有效。目前。

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    CGFloat webViewHeight = 0.0f;
    if (self.subviews.count > 0) {
        UIView *scrollerView = [self.subviews objectAtIndex:0];
        if (scrollerView.subviews.count > 0) {
            UIView *webDocView = scrollerView.subviews.lastObject;
            if ([webDocView isKindOfClass:[NSClassFromString(@"UIWebDocumentView") class]])
                webViewHeight = webDocView.frame.size.height;
        }
    }
}

如果失败,它应该安全地返回0。


3
与[webview stringByEvaluatingJavaScriptFromString:@“ document.getElementById(\” foo \“)。offsetHeight;”];相比,它有什么好处?问题在于,webview在完成加载之前无法返回其大小,当表需要知道其大小时,webview可能不会返回该大小。
Erik B 2010年

4

问题-sizeThatFits:在于它无法立即使用,至少在iOS 4.1上无法使用。它仅返回webView的当前大小(无论是使用CGSizeZero调用还是使用任意非零大小)。

我发现,如果在调用之前降低webView的框架高度,则它实际上可以工作-sizeThatFits:

请参阅我的解决方案:如何确定UIWebView的内容大小?


谢谢你的指点。遇到此问题时,我确实看到了您的解决方案,但就我而言,这种方法无法更好地工作。我真的不记得我需要什么,但是最后我以不同的方式做了。
Shade

4

更好的方法是使用scrollView.contentSize.height属性,如下所示。

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
     NSLog(@"%f",webView.scrollView.contentSize.height);   
}

1
对我来说,它是scrollView.contentSize.height-CGRectGetHeight(scrollView.frame)。stackoverflow.com/a/39386880/1677041
Itachi

3

如果您第一次使用sizeThatFits值不正确,但之后没有,那么我遇到的可能原因是:外部CSS的错误。似乎在检索外部CSS和完全构建Web文档之前不久将调用webViewDidFinisLoad。我认为如果您重新加载缓存,该错误就会消失。

一个窍门:很快在您的应用程序中用一个虚拟的UIWebView预加载CSS。

SDK:IOS4


就我而言,加载的不是CSS,而是CSS中的字体文件。
beetstra

3

测量Web视图是有效的,但仅当它加载了其内容时

  • 使网页视图变小(如5px)
  • 加载并等待完成
  • 然后调用sizeToFit
  • 得到大小然后
  • 重新加载tableview(返回单元格的正确高度)

广告::D在github上看到我的M42WebviewTableViewCell类,为此感到困扰


这样可行!谢谢,我之前使用过javascript方法,但是这一方法对我来说效果更好。
Stan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.