获得样式化的UIWebView内容的大小 - 不太合适

时间:2012-07-25 00:49:04

标签: ios uiwebview

这似乎是一个常见问题,但我找不到合适的解决方案。我正在尝试重新调整一堆UIWebView以适应他们的内容,但它似乎无法正常工作。到目前为止我找到的最佳解决方案是this answer,但它似乎只在我的解决方案中偶尔使用。我们的想法是在webViewDidFinishLoad:委托方法中重新调整UIWebView的大小。但是,这仍然无法获得正确的尺寸。如果我在 webViewDidFinishLoad:之后的某个未定义时间触发更新,则内容的大小确实正确。

我将在下面描述我的情况,并在Gist上粘贴相关来源。

问题说明

我遇到的情况是我从JSON API获取数据并在webview中显示数据。 API返回一个对象数组,每个对象都有一个带有HTML格式文本的“content”字段。设计师给出了一个结构,其中包含一个(大部分)隐藏的视图,您可以向上滑动显示,其中包含所有内容的滚动视图,以非常特殊的方式进行格式化。

为了实现这一点,我有三个视图控制器:主视图控制器,您在主视图控制器上向上滑动以显示的辅助视图控制器,以及显示一个html格式内容的三级视图控制器JSON API结果。
辅助视图控制器包含UIScrollView和一组第三视图控制器。每个第三视图控制器都包含一个UIWebView,用于显示HTML格式的内容,以及用于显示JSON对象的其他属性的标签。因为第三视图将显示在辅助视图中的UIScrollView内,所以需要重新调整第三视图的UIWebView以适合其内容并禁用用户交互以防止滚动视图中的滚动视图混乱场景。

让所有这一切发挥作用的过程如下:

  1. 首先,在主控制器ViewDidLoad上,加载并显示辅助视图 和一个活动指示器,以便UI看起来不会冻结
  2. 接下来,从JSON API加载数据
  3. 当加载API的数据(通过委托通知)时,构建第三级 查看控制器,从加载的数据中设置其属性并将其添加到辅助节点 控制器清单。
  4. 完成后,调用辅助控制器的设置方法。这种方法循环 通过三级控制器列表并依次调用其设置方法
  5. 每个三级控制器的设置方法设置标签的文本并设置 UIWebView的内容使用loadHTMLString:和预定义的html文件的内容, 将JSON对象的内容替换为。
  6. 在三级控制器的webViewDidFinishLoad:委托方法中,使用 this answer处的方法,根据内容大小调整网页视图的大小。
  7. 调整三级控制器视图的大小以适合Web视图并定位任何标签 进入网络视图下方
  8. 然后,三级控制器调用委托方法来通知辅助控制器 它已经完成加载。辅助控制器会监视其中的哪个 三级控制器已完成装载。
  9. 当所有三级控制器完成加载时,辅助控制器循环 通过它的列表并将第三视图添加到它的UIScrollView的内容中,进行调整 框架和内容高度。

2 个答案:

答案 0 :(得分:6)

如果您使用的是iOS 5.0,则可以使用webview.scrollView.contentsize,否则您也可以通过javascript获取内容大小。

CGFloat newHeight = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.offsetHeight;"] floatValue];

或者

CGFloat newHeight = [[webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.scrollHeight;"] floatValue];

答案 1 :(得分:0)

我知道你有一个解决方案,但我自己也解决了这个问题,我想出了一个简单而又愚蠢的答案。

起初我的UIWebView只会增长,但永远不会缩小。所以我开始尝试设置帧大小,但它会尝试滚动一个太小的帧,所以我每次加载一些东西时都会将contentSize.height设置为1。我的完成负载看起来像这样

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSLog(@"--- webViewDidFinishLoad (pre sizeToFit) webview.frame = %@", NSStringFromCGRect(_detailsWebView.frame));
    NSLog(@"--- webViewDidFinishLoad (pre sizeToFit) scrollview.contentSize = %@", NSStringFromCGSize(_detailsWebView.scrollView.contentSize));
    [_detailsWebView sizeToFit];
    NSLog(@"--- webViewDidFinishLoad (post sizeToFit) scrollview.contentSize = %@", NSStringFromCGSize(_detailsWebView.scrollView.contentSize));
    NSLog(@"--- webViewDidFinishLoad (post sizeToFit) webview.frame = %@", NSStringFromCGRect(_detailsWebView.frame));
}

但这给了我输出

[8431:707] --- webViewDidFinishLoad (pre sizeToFit) webview.frame = {{20, 11}, {663, 757}}
[8431:707] --- webViewDidFinishLoad (pre sizeToFit) scrollview.contentSize = {663, 1}
[8431:707] --- webViewDidFinishLoad (post sizeToFit) scrollview.contentSize = {663, 92}
[8431:707] --- webViewDidFinishLoad (post sizeToFit) webview.frame = {{20, 11}, {663, 1}}

只要我的“新”内容比我的旧内容更大,它现在有效,但如果内容缩小,则会出现问题。事实证明,sizeToFit在更新frame之前contentSize更新了frame

我能够通过在调用contentSize后手动更新sizeToFit中的sizeToFit来解决此问题,最终,我连续两次调用- (void)webViewDidFinishLoad:(UIWebView *)webView { [_detailsWebView sizeToFit]; [_detailsWebView sizeToFit]; }

{{1}}

它有效。我不能说我对这样的解决方案感到满意,并且我正在努力使它变得更好,但它的工作原理和代码非常简单。