私が持っているUIWebView
別の(単一ページ)コンテンツに。CGSize
親ビューを適切にサイズ変更するためのコンテンツを見つけたいのですが。明らかに-sizeThatFits:
残念ながら、webViewの現在のフレームサイズを返します。
私が持っているUIWebView
別の(単一ページ)コンテンツに。CGSize
親ビューを適切にサイズ変更するためのコンテンツを見つけたいのですが。明らかに-sizeThatFits:
残念ながら、webViewの現在のフレームサイズを返します。
回答:
私の最初の推測-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);
}
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
}
JavaScriptを使用した別のアプローチ(@GregInYEGに感謝)があることを指摘しておきます。どのソリューションの方がパフォーマンスが良いかわかりません。
2つのハッキングソリューションのうち、私はこれをより気に入っています。
UIWebView
です、あなたの親ビューよりも高い場合、それをに埋め込む必要がありますUIScrollView
。
うまくいく別の解決策があります。
一方では、Ortwinのアプローチとソリューションは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
がに埋め込まれている)の複雑な状況でもscrollView
。
以下は、Layoutのレイアウトを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.
}
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;
}
私の例では、という注意webView
カスタムに埋め込まれたscrollView
他のを持っwebViews
...これらすべてがwebViews
自分を持っていたwebView.scrollView.scrollEnabled = NO
、と私は追加する必要がありましたコードの最後の部分は計算だったheight
のcontentSize
私のカスタムのscrollView
これらを埋め込むwebViews
が、それは簡単なようでした上記のトリックで計算された私webView
のを合計frame.size.height
すると...
-[UIWebView scrollView]
iOS 5.0以降でのみ使用できます。
Ortwinの答えがほとんどの時間しか機能しないことに気付いたため、この質問を復活させます...
このwebViewDidFinishLoad
メソッドは複数回呼び出される場合があり、によって返される最初の値はsizeThatFits
、最終的なサイズの一部にすぎません。次に、なんらかの理由で次のsizeThatFits
whenの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;
}
スウィフト(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
}
}
更新:私はコメントで述べたように、コンテンツが縮小したケースをキャッチしていないようです。すべてのコンテンツとOSバージョンに当てはまるかどうかわからない場合は、試してみてください。
webView.scalesPageToFit = YES
は、上記のコメントで言及されている@Sijoのように与えない場合にのみ機能します。
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)")
}
単純な解決策は単に使用するwebView.scrollView.contentSize
ことですが、これがJavaScriptで動作するかどうかはわかりません。JavaScriptが使用されていない場合、これは確実に機能します。
- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
CGSize contentSize = aWebView.scrollView.contentSize;
NSLog(@"webView contentSize: %@", NSStringFromCGSize(contentSize));
}
これは変だ!
私は解決策をテストし、両方sizeThatFits:
と[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"]
されないで私のために働い。
しかし、ウェブページのコンテンツの適切な高さを取得する興味深い簡単な方法を見つけました。現在、デリゲートメソッドで使用していscrollViewDidScroll:
ます。
CGFloat contentHeight = scrollView.contentSize.height - CGRectGetHeight(scrollView.frame);
iOS 9.3シミュレーター/デバイスで確認済み、頑張ってください!
編集:
背景:HTMLコンテンツは、文字列変数とHTTPコンテンツテンプレートによって計算され、methodによって読み込まれloadHTMLString:baseURL:
ます。登録されたJSスクリプトはありません。
私が使用しているUIWebView
サブビューではありません(したがって、ウィンドウ階層の一部ではない)のためのHTMLコンテンツのサイズを決定することUITableViewCells
。切断UIWebView
すると、でサイズが適切に報告されないことがわかりました-[UIWebView sizeThatFits:]
。で述べたようにまた、https://stackoverflow.com/a/3937599/9636、あなたが設定しなければならないUIWebView
のframe
height
全ての適切な高さを得るために1にします。
UIWebView
の高さが高すぎる場合(つまり、高さが1000に設定されているが、HTMLコンテンツのサイズが500しかない場合):
UIWebView.scrollView.contentSize.height
-[UIWebView stringByEvaluatingJavaScriptFromString:@"document.height"]
-[UIWebView sizeThatFits:]
すべてのa height
は1000を返します。
この場合の問題を解決するために、私はhttps://stackoverflow.com/a/11770883/9636を使用しました。ただし、私UIWebView.frame.width
がと同じ場合にのみ、このソリューションを使用し-[UIWebView sizeThatFits:]
width
ます。
ここでの提案のどれも私の状況に役立ちませんでしたが、私は私に答えを与える何かを読みました。UIControllerの固定セットとそれに続くUIWebViewを備えたViewControllerがあります。UIコントロールがHTMLコンテンツに接続されているかのようにページ全体をスクロールさせたいので、UIWebViewでのスクロールを無効にし、親スクロールビューのコンテンツサイズを正しく設定する必要があります。
重要なヒントは、UIWebViewが画面にレンダリングされるまでサイズを正しく報告しないことです。そのため、コンテンツをロードするときに、コンテンツサイズを使用可能な画面の高さに設定しました。次に、viewDidAppearで、スクロールビューのコンテンツサイズを正しい値に更新します。ローカルコンテンツでloadHTMLStringを呼び出しているので、これはうまくいきました。loadRequestを使用している場合は、htmlの取得速度によっては、webViewDidFinishLoadのcontentSizeも更新する必要がある場合があります。
スクロールビューの非表示部分のみが変更されるため、ちらつきはありません。
webViewDidFinishLoad
安全なアプローチとして頼りにしたいと思います。
HTMLにiframeなどの重い HTMLコンテンツ(つまり、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-更新WebViewの高さのあなたに-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.
...
PS ObjectiveC / Swiftコード内で時間遅延(SetTimeoutおよびsetInterval)を実装できます-それはあなた次第です。
PSS UIWebViewとFacebook埋め込みに関する重要な情報:埋め込まれたFacebook投稿がUIWebViewに正しく表示されません
私もこの問題で立ち往生していて、webViewの動的な高さを計算する場合は、最初にwebViewの幅を指定する必要があるので、jsの前に1行追加するとわかります。非常に正確な実際の高さ。
コードは次のように単純です:
-(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;
//......
}
また、iOS 7では、前述のすべてのメソッドを適切に機能させるために、ビューコントローラーviewDidLoad
メソッドに次のコードを追加します。
if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) {
self.automaticallyAdjustsScrollViewInsets = NO;
}
そうしないと、どちらのメソッドも正常に機能しません。