Ios 如何确定UIWebView的内容大小?
我有一个具有不同(单页)内容的Ios 如何确定UIWebView的内容大小?,ios,iphone,cocoa-touch,uiwebview,uikit,Ios,Iphone,Cocoa Touch,Uiwebview,Uikit,我有一个具有不同(单页)内容的UIWebView。我想找出内容的CGSize,以适当调整父视图的大小。显而易见的-sizehatfits:不幸的是,它只返回了webView的当前帧大小。好吧,你可以使用[webView-sizehatfits:CGSizeZero]来计算它的内容大小。事实证明,我第一次使用-sizehatfits:的猜测并不是完全错误的。这似乎是可行的,但只有在发送-sizeThatFits:之前,将webView的框架设置为最小尺寸时,它才会起作用。之后,我们可以通过合适的尺
UIWebView
。我想找出内容的CGSize
,以适当调整父视图的大小。显而易见的-sizehatfits:
不幸的是,它只返回了webView的当前帧大小。好吧,你可以使用[webView-sizehatfits:CGSizeZero]
来计算它的内容大小。事实证明,我第一次使用-sizehatfits:
的猜测并不是完全错误的。这似乎是可行的,但只有在发送-sizeThatFits:
之前,将webView的框架设置为最小尺寸时,它才会起作用。之后,我们可以通过合适的尺寸来纠正错误的框架尺寸。这听起来很糟糕,但实际上没那么糟糕。由于我们两个帧都在彼此之后进行更改,因此视图不会更新,也不会闪烁
当然,我们必须等待内容加载完毕,因此我们将代码放入-webviewdiffinishload:
委托方法中
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);
}
- (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.
}
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
}
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;
}
我要指出的是(谢谢@GregInYEG)在使用JavaScript。不确定哪种解决方案性能更好
在两个黑客解决方案中,我更喜欢这一个。重新提出这个问题,因为我发现Ortwin的答案在大多数情况下都是有效的
webviewdiffinishload
方法可能会被多次调用,而sizehattfits
返回的第一个值只是最终大小的一部分。然后,无论出于何种原因,当再次激发webViewDidFinishLoad
时,对sizeThatFits
的下一次调用将错误地返回与之前相同的值!对于相同的内容,这将随机发生,就像是某种并发问题一样。也许随着时间的推移,这种行为已经发生了变化,因为我正在为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;
}
Swift(2.2):
更新:我发现正如评论中提到的,这似乎没有抓住内容缩水的情况。不确定它是否适用于所有内容和操作系统版本,请试一试。我有另一个解决方案非常有效 一方面,Ortwin的方法和解决方案仅适用于iOS 6.0及更高版本,但无法在iOS 5.0、5.1和5.1.1上正常工作,另一方面,我不喜欢和不理解Ortwin的方法,这是使用方法
[webView sizeThatFits:CGSizeZero]
带有参数CGSizeZero
:如果你阅读了苹果公司关于此方法及其参数的官方文档,它会清楚地说:
此方法的默认实现返回视图边框的大小部分。子类可以重写此方法,以基于任何子视图的所需布局返回自定义值。例如,UISwitch对象返回表示开关视图标准大小的固定大小值,UIImageView对象返回当前显示的图像大小
我的意思是,这就像他在没有任何逻辑的情况下遇到了他的解决方案,因为阅读文档时,传递给[webView sizeThatFits:…]
的参数至少应该具有所需的宽度。使用他的解决方案,在使用CGSizeZero
参数调用sizehatfits
之前,将所需的宽度设置为webView
的框架。所以我认为这个解决方案是“偶然”在iOS 6上运行的
我设想了一种更合理的方法,它的优点是适用于iOS 5.0及更高版本。。。而且在复杂的情况下,scrollView
中嵌入了多个webView(其属性为webView.scrollView.scrollEnabled=NO
)
下面是我的代码,用于强制将webView
的布局设置为所需的宽度
,并将相应的高度
设置回webView
本身:
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);
}
- (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.
}
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
}
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
中,该视图具有其他webView
…所有这些webView
都有它们的webView.scrollView.scrollEnabled=NO
,我必须添加的最后一段代码是计算contentSize的高度我的自定义scrollView
的de>嵌入了这些webView
,但这很容易,只要将我的webView的frame.size.height
相加,就可以用上面描述的技巧计算出来……我使用的UIWebView
不是子视图(因此不是窗口层次结构的一部分)要确定UITableViewCells
的HTML内容大小,我发现断开连接的UIWebView
无法使用-[UIWebView sizeThatFits:]正确报告其大小
。此外,如中所述,您必须将UIWebView
的框架
高度
设置为1,才能获得正确的高度
如果UIWebView
的高度太大(即设置为1000,但HTML内容大小仅为500):
全部返回1000的高度
为了解决本例中的问题,我使用了,我尽职尽责地投了赞成票。但是,我仅在我的UIWebView.frame.width
与-[UIWebView sizethattfits:]相同时才使用此解决方案
width
一个简单的解决方案是只使用webView.scrollView.contentSize
,但我不知道这是否适用于JavaScript。如果没有使用JavaScript,这肯定有效:
- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
CGSize contentSize = aWebView.scrollView.contentSize;
NSLog(@"webView contentSize: %@", NSStringFromCGSize(contentSize));
}
同样在iOS 7中,为了正确使用所有提到的方法,请在视图控制器viewDidLoad
方法中添加以下内容:
if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) {
self.automaticallyAdjustsScrollViewInsets = NO;
}
否则,这两种方法都不起作用
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;
}
...
...
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.
...
- (void)webViewDidFinishLoad:(UIWebView *)webView {
webView.scrollView.scrollEnabled = NO;
_webViewHeight.constant = webView.scrollView.contentSize.height;
}
CGFloat contentHeight = scrollView.contentSize.height - CGRectGetHeight(scrollView.frame);
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
CGFloat height = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
NSLog(@"Webview height is:: %f", height);
}
func webViewDidFinishLoad(aWebView:UIWebView){
let height: Float = (aWebView.stringByEvaluatingJavaScriptFromString("document.body.scrollHeight")?.toFloat())!
print("Webview height is::\(height)")
}