我有UIWebView
个不同的(单页)内容。我想找出内容的CGSize
来适当调整父视图的大小。遗憾的是,-sizeThatFits:
只返回webView的当前帧大小。
答案 0 :(得分:249)
事实证明,我使用-sizeThatFits:
的第一次猜测并非完全错误。它似乎有效,但前提是在发送-sizeThatFits:
之前将webView的框架设置为最小尺寸。之后,我们可以通过拟合尺寸校正错误的框架尺寸。这听起来很可怕,但实际上并没有那么糟糕。由于我们彼此之后都进行了两次帧更改,因此视图不会更新,也不会闪烁。
当然,我们必须等到内容加载完毕,因此我们将代码放入-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);
}
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
}
我应该指出another approach(感谢@GregInYEG)使用JavaScript。不确定哪种解决方案表现更好。
在两个hacky解决方案中,我更喜欢这个。
答案 1 :(得分:90)
我有另一种效果很好的解决方案。
一方面,Ortwin的方法&amp;解决方案仅适用于iOS 6.0及更高版本,但无法在iOS 5.0,5.1和5.1.1上正常工作,另一方面,有些东西我不喜欢也无法用Ortwin的方法理解,这是用法参数[webView sizeThatFits:CGSizeZero]
的方法CGSizeZero
:如果您阅读Apple官方文档有关此方法及其参数的信息,则说明清楚:
此方法的默认实现返回视图边界矩形的大小部分。子类可以覆盖此方法,以根据所需子视图的所需布局返回自定义值。例如,UISwitch对象返回一个固定大小的值,表示切换视图的标准大小,UIImageView对象返回当前显示的图像大小。
我的意思是,就像他在没有任何逻辑的情况下遇到他的解决方案一样,因为阅读文档时,传递给[webView sizeThatFits: ...]
的参数应该至少具有所需的width
。使用他的解决方案,在使用webView
参数调用sizeThatFits
之前,将所需宽度设置为CGSizeZero
的帧。所以我认为这个解决方案是通过“偶然”在iOS 6上工作的。
我想象一种更合理的方法,它具有适用于iOS 5.0及更高版本的优势......而且在复杂的情况下,其中多个webView(其属性webView.scrollView.scrollEnabled = NO
嵌入在{{1}中}}
以下是我的代码,强制将scrollView
的布局强制转换为所需的webView
,然后将相应的width
设置回height
本身:
<强>的OBJ-C 强>
webView
Swift 4.x
- (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.
}
请注意,在我的示例中,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;
}
嵌入了具有其他webView
的自定义scrollView
...所有这些webViews
都有webViews
,我必须添加的最后一段代码是计算嵌入这些webView.scrollView.scrollEnabled = NO
的自定义height
的{{1}}的{{1}},但它就像汇总一样简单我的contentSize
scrollView
使用上述技巧进行计算...
答案 2 :(得分:22)
在Xcode 8和iOS 10中确定Web视图的高度。你可以使用
获得身高- (void)webViewDidFinishLoad:(UIWebView *)webView
{
CGFloat height = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
NSLog(@"Webview height is:: %f", height);
}
或者对于Swift
func webViewDidFinishLoad(aWebView:UIWebView){
let height: Float = (aWebView.stringByEvaluatingJavaScriptFromString("document.body.scrollHeight")?.toFloat())!
print("Webview height is::\(height)")
}
答案 3 :(得分:8)
一个简单的解决方案就是使用webView.scrollView.contentSize
,但我不知道这是否适用于JavaScript。如果没有使用JavaScript,这肯定有用:
- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
CGSize contentSize = aWebView.scrollView.contentSize;
NSLog(@"webView contentSize: %@", NSStringFromCGSize(contentSize));
}
答案 4 :(得分:3)
AFAIK,您可以使用[webView sizeThatFits:CGSizeZero]
来确定其内容大小。
答案 5 :(得分:3)
这很奇怪!
我测试了sizeThatFits:
和[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"]
NOT 为我工作的解决方案。
然而,我找到了一种有趣的方法来获得正确的网页内容。目前,我在委托方法scrollViewDidScroll:
中使用了它。
CGFloat contentHeight = scrollView.contentSize.height - CGRectGetHeight(scrollView.frame);
在iOS 9.3模拟器/设备中验证,祝你好运!
修改强>
背景:html内容由我的字符串变量和HTTP内容模板计算,由方法loadHTMLString:baseURL:
加载,没有注册的JS脚本。
答案 6 :(得分:3)
对于iOS10,我得到document.height
的0(零)值,因此document.body.scrollHeight
是获取Webview中文档高度的解决方案。 width
也可以解决该问题。
答案 7 :(得分:2)
我正在使用不是子视图的UIWebView
(因此不是窗口层次结构的一部分)来确定UITableViewCells
的HTML内容的大小。我发现,已断开连接的UIWebView
未使用-[UIWebView sizeThatFits:]
正确报告其大小。此外,正如https://stackoverflow.com/a/3937599/9636中所述,您必须将UIWebView
的{{1}} frame
设置为1才能获得正确的高度。
如果height
的高度太大(即您将其设置为1000,但HTML内容大小仅为500):
UIWebView
全部返回UIWebView.scrollView.contentSize.height
-[UIWebView stringByEvaluatingJavaScriptFromString:@"document.height"]
-[UIWebView sizeThatFits:]
1000。
为解决我在这种情况下遇到的问题,我使用https://stackoverflow.com/a/11770883/9636,我尽职尽责地投票。但是,当height
与UIWebView.frame.width
-[UIWebView sizeThatFits:]
相同时,我才使用此解决方案。
答案 8 :(得分:2)
这里的建议都没有帮助我解决我的情况,但我读了一些确实给我答案的东西。我有一个ViewController,其中包含一组固定的UI控件,后跟一个UIWebView。我希望整个页面滚动,好像UI控件已连接到HTML内容,因此我禁用UIWebView上的滚动,然后必须正确设置父滚动视图的内容大小。
重要提示原来是UIWebView在呈现到屏幕之前不会正确报告其大小。因此,当我加载内容时,我将内容大小设置为可用的屏幕高度。然后,在viewDidAppear中,我将scrollview的内容大小更新为正确的值。这对我有用,因为我在本地内容上调用loadHTMLString。如果您正在使用loadRequest,则可能还需要更新webViewDidFinishLoad中的contentSize,具体取决于检索html的速度。
没有闪烁,因为只有滚动视图的不可见部分被更改。
答案 9 :(得分:2)
如果你的HTML包含重 HTML内容,例如iframe(即facebook-,twitter,instagram-embeds),真正的解决方案要困难得多,首先打包你的HTML:
[htmlContent appendFormat:@"<html>", [[LocalizationStore instance] currentTextDir], [[LocalizationStore instance] currentLang]];
[htmlContent appendFormat:@"<head>"];
[htmlContent appendString:@"<script type=\"text/javascript\">"];
[htmlContent appendFormat:@" var lastHeight = 0;"];
[htmlContent appendFormat:@" function updateHeight() { var h = document.getElementById('content').offsetHeight; if (lastHeight != h) { lastHeight = h; window.location.href = \"x-update-webview-height://\" + h } }"];
[htmlContent appendFormat:@" window.onload = function() {"];
[htmlContent appendFormat:@" setTimeout(updateHeight, 1000);"];
[htmlContent appendFormat:@" setTimeout(updateHeight, 3000);"];
[htmlContent appendFormat:@" if (window.intervalId) { clearInterval(window.intervalId); }"];
[htmlContent appendFormat:@" window.intervalId = setInterval(updateHeight, 5000);"];
[htmlContent appendFormat:@" setTimeout(function(){ clearInterval(window.intervalId); window.intervalId = null; }, 30000);"];
[htmlContent appendFormat:@" };"];
[htmlContent appendFormat:@"</script>"];
[htmlContent appendFormat:@"..."]; // Rest of your HTML <head>-section
[htmlContent appendFormat:@"</head>"];
[htmlContent appendFormat:@"<body>"];
[htmlContent appendFormat:@"<div id=\"content\">"]; // !important https://stackoverflow.com/a/8031442/1046909
[htmlContent appendFormat:@"..."]; // Your HTML-content
[htmlContent appendFormat:@"</div>"]; // </div id="content">
[htmlContent appendFormat:@"</body>"];
[htmlContent appendFormat:@"</html>"];
然后将处理 x-update-webview-height -scheme添加到 shouldStartLoadWithRequest 中:
if (navigationType == UIWebViewNavigationTypeLinkClicked || navigationType == UIWebViewNavigationTypeOther) {
// Handling Custom URL Scheme
if([[[request URL] scheme] isEqualToString:@"x-update-webview-height"]) {
NSInteger currentWebViewHeight = [[[request URL] host] intValue];
if (_lastWebViewHeight != currentWebViewHeight) {
_lastWebViewHeight = currentWebViewHeight; // class property
_realWebViewHeight = currentWebViewHeight; // class property
[self layoutSubviews];
}
return NO;
}
...
最后在 layoutSubviews 中添加以下代码:
...
NSInteger webViewHeight = 0;
if (_realWebViewHeight > 0) {
webViewHeight = _realWebViewHeight;
_realWebViewHeight = 0;
} else {
webViewHeight = [[webView stringByEvaluatingJavaScriptFromString:@"document.getElementById(\"content\").offsetHeight;"] integerValue];
}
upateWebViewHeightTheWayYorLike(webViewHeight);// Now your have real WebViewHeight so you can update your webview height you like.
...
P.S。你可以在ObjectiveC / Swift代码中实现时间延迟(SetTimeout和setInterval) - 这取决于你。
P.S.S。关于UIWebView和Facebook Embeds的重要信息:Embedded Facebook post does not shows properly in UIWebView
答案 10 :(得分:2)
在scrollview中的某个地方使用webview作为子视图时,可以将高度约束设置为某个常量值,然后从中输出并使用它,如下所示:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
webView.scrollView.scrollEnabled = NO;
_webViewHeight.constant = webView.scrollView.contentSize.height;
}
答案 11 :(得分:1)
我也坚持这个问题,然后我意识到如果我想计算webView的动态高度,我需要首先告诉webView的宽度,所以我在js之前添加一行,结果证明我可以得到非常准确的实际高度。
代码很简单:
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
//tell the width first
webView.width = [UIScreen mainScreen].bounds.size.width;
//use js to get height dynamically
CGFloat scrollSizeHeight = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
webView.height = scrollSizeHeight;
webView.x = 0;
webView.y = 0;
//......
}
答案 12 :(得分:1)
Xcode8 swift3.1:
webViewDidFinishLoad
代表: let height = webView.scrollView.contentSize.height
没有step1,如果是webview.height&gt;实际contentHeight,第2步将返回webview.height但不返回contentsize.height。
答案 13 :(得分:0)
同样在iOS 7中正确使用所有提到的方法,在视图控制器viewDidLoad
方法中添加:
if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) {
self.automaticallyAdjustsScrollViewInsets = NO;
}
否则这两种方法都不会起作用。