如何确定UIWebView的内容大小?

Ort*_*ntz 116 iphone cocoa-touch uiwebview uikit ios

我有一个UIWebView不同的(单页)内容.我想找出CGSize适当调整父视图大小的内容.-sizeThatFits:不幸的是,显而易见的只是返回webView的当前帧大小.

Ort*_*ntz 249

事实证明,我的第一次使用猜测-sizeThatFits:并非完全错误.它似乎工作,但只有在发送之前webView的框架设置为最小尺寸-sizeThatFits:.之后,我们可以通过拟合尺寸校正错误的框架尺寸.这听起来很可怕,但实际上并没有那么糟糕.由于我们彼此之后都进行了两次帧更改,因此视图不会更新且不会闪烁.

当然,我们必须等到内容加载完毕,因此我们将代码放入-webViewDidFinishLoad:委托方法中.

OBJ-C

- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
    CGRect frame = aWebView.frame;
    frame.size.height = 1;
    aWebView.frame = frame;
    CGSize fittingSize = [aWebView sizeThatFits:CGSizeZero];
    frame.size = fittingSize;
    aWebView.frame = frame;

    NSLog(@"size: %f, %f", fittingSize.width, fittingSize.height);
}
Run Code Online (Sandbox Code Playgroud)

Swift 4.x

func webViewDidFinishLoad(_ webView: UIWebView) {
    var frame = webView.frame
    frame.size.height = 1
    webView.frame = frame
    let fittingSize = webView.sizeThatFits(CGSize.init(width: 0, height: 0))
    frame.size = fittingSize
    webView.frame = frame
}
Run Code Online (Sandbox Code Playgroud)

我应该指出使用JavaScript 的另一种方法(感谢@GregInYEG).不确定哪种解决方案表现更好.

在两个hacky解决方案中,我更喜欢这个.

  • 如果我给webView.scalesPageToFit = YES; 然后只有这个解决方案工作..谢谢解决方案.. (7认同)

小智 92

我有另一个很好的解决方案.

一方面,Ortwin的方法和解决方案仅适用于iOS 6.0及更高版本,但无法在iOS 5.0,5.1和5.1.1上正常工作,另一方面,有些东西我不喜欢也无法理解使用Ortwin的方法,使用[webView sizeThatFits:CGSizeZero]带参数的方法CGSizeZero:如果您阅读有关此方法及其参数的Apple官方文档,它会清楚地说明:

此方法的默认实现返回视图边界矩形的大小部分.子类可以覆盖此方法,以根据所需子视图的所需布局返回自定义值.例如,UISwitch对象返回一个固定大小的值,表示切换视图的标准大小,UIImageView对象返回当前显示的图像的大小.

我的意思是,就像他在没有任何逻辑的情况下遇到他的解决方案一样,因为阅读文档,传递给的参数[webView sizeThatFits: ...]应该至少具有所需的width.使用他的解决方案,在使用参数webView调用之前,将所需宽度设置为's frame .所以我认为这个解决方案是通过"偶然"在iOS 6上运行的.sizeThatFitsCGSizeZero

我想象一种更合理的方法,它具有适用于iOS 5.0及更高版本的优势......而且在复杂的情况下,其中有多个webView(其属性webView.scrollView.scrollEnabled = NO嵌入在scrollView.

这是我的代码强制webView到所需的布局width并获得相应的height设置回webView自身:

OBJ-C

- (void)webViewDidFinishLoad:(UIWebView *)aWebView
{   
    aWebView.scrollView.scrollEnabled = NO;    // Property available in iOS 5.0 and later 
    CGRect frame = aWebView.frame;

    frame.size.width = 200;       // Your desired width here.
    frame.size.height = 1;        // Set the height to a small one.

    aWebView.frame = frame;       // Set webView's Frame, forcing the Layout of its embedded scrollView with current Frame's constraints (Width set above).

    frame.size.height = aWebView.scrollView.contentSize.height;  // Get the corresponding height from the webView's embedded scrollView.

    aWebView.frame = frame;       // Set the scrollView contentHeight back to the frame itself.
}
Run Code Online (Sandbox Code Playgroud)

Swift 4.x

func webViewDidFinishLoad(_ aWebView: UIWebView) {

    aWebView.scrollView.isScrollEnabled = false
    var frame = aWebView.frame

    frame.size.width = 200
    frame.size.height = 1

    aWebView.frame = frame
    frame.size.height = aWebView.scrollView.contentSize.height

    aWebView.frame = frame;
}
Run Code Online (Sandbox Code Playgroud)

请注意,在我的例子中,webView被嵌入到定制scrollView具有其它webViews......所有这些webViews有他们webView.scrollView.scrollEnabled = NO,并且代码的最后一块,我不得不添加了的计算heightcontentSize我的自定义的scrollView嵌入这些webViews,但它是那么容易用上面描述的技巧计算我webViewframe.size.height计算结果......

  • 这比公认的解决方案更优雅,并且它不依赖于未记录和未定义的行为.这比插入javascript要少得多.我希望我可以64次投票. (3认同)
  • 我尝试了这个和类似的解决方案,结果证明只有webview或嵌入的视图已经在屏幕上才有效.如果在将webview添加到视图层次结构之前尝试此操作,则结果将是手动大小高度. (2认同)

Kie*_*per 37

复活这个问题是因为我发现Ortwin的答案只适用于大部分时间......

webViewDidFinishLoad方法可以被多次调用,并且返回的第一个值sizeThatFits只是最终大小应该是的一部分.然后无论出于何种原因,再次触发sizeThatFits时的下一次调用webViewDidFinishLoad将错误地返回之前执行的相同值!对于相同的内容,这将是随机发生的,就好像它是某种并发问题一样.也许这种行为随着时间的推移而发生了变化,因为我正在为iOS 5构建,并且发现它的sizeToFit工作方式大致相同(虽然之前没有这样做?)

我已经解决了这个简单的解决方案:

- (void)webViewDidFinishLoad:(UIWebView *)aWebView
{        
    CGFloat height = [[aWebView stringByEvaluatingJavaScriptFromString:@"document.height"] floatValue];
    CGFloat width = [[aWebView stringByEvaluatingJavaScriptFromString:@"document.width"] floatValue];
    CGRect frame = aWebView.frame;
    frame.size.height = height;
    frame.size.width = width;
    aWebView.frame = frame;
}
Run Code Online (Sandbox Code Playgroud)

斯威夫特(2.2):

func webViewDidFinishLoad(webView: UIWebView) {

    if let heightString = webView.stringByEvaluatingJavaScriptFromString("document.height"),
        widthString = webView.stringByEvaluatingJavaScriptFromString("document.width"),
        height = Float(heightString),
        width = Float(widthString) {

        var rect = webView.frame
        rect.size.height = CGFloat(height)
        rect.size.width = CGFloat(width)
        webView.frame = rect
    }
}
Run Code Online (Sandbox Code Playgroud)

更新:我发现在评论中提到这似乎没有抓住内容缩小的情况.不确定所有内容和操作系统版本是否属实,请试一试.


Har*_*kar 22

在Xcode 8和iOS 10中确定Web视图的高度.你可以使用高度

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    CGFloat height = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
    NSLog(@"Webview height is:: %f", height);
}
Run Code Online (Sandbox Code Playgroud)

或者对于斯威夫特

 func webViewDidFinishLoad(aWebView:UIWebView){
        let height: Float = (aWebView.stringByEvaluatingJavaScriptFromString("document.body.scrollHeight")?.toFloat())!
        print("Webview height is::\(height)")
    }
Run Code Online (Sandbox Code Playgroud)


Oem*_*erA 8

一个简单的解决方案就是使用,webView.scrollView.contentSize但我不知道这是否适用于JavaScript.如果没有使用JavaScript,这肯定有效:

- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
    CGSize contentSize = aWebView.scrollView.contentSize;
    NSLog(@"webView contentSize: %@", NSStringFromCGSize(contentSize));
}
Run Code Online (Sandbox Code Playgroud)