Ben var UIWebView
farklı (tek sayfa) içeriği ile. CGSize
Ana görünümlerimi uygun şekilde yeniden boyutlandırmak için içeriğin ne olduğunu öğrenmek istiyorum . Bariz olan şey -sizeThatFits:
maalesef webView’un geçerli çerçeve boyutunu döndürür.
Ben var UIWebView
farklı (tek sayfa) içeriği ile. CGSize
Ana görünümlerimi uygun şekilde yeniden boyutlandırmak için içeriğin ne olduğunu öğrenmek istiyorum . Bariz olan şey -sizeThatFits:
maalesef webView’un geçerli çerçeve boyutunu döndürür.
Yanıtlar:
İlk tahminimin kullanımının -sizeThatFits:
tamamen yanlış olmadığı ortaya çıktı . Çalışıyor gibi görünüyor, ancak yalnızca webView çerçevesi gönderilmeden önce minimum boyuta ayarlanmışsa -sizeThatFits:
. Bundan sonra, yanlış çerçeve boyutunu uygun boyuta göre düzeltebiliriz. Kulağa korkunç geliyor ama aslında o kadar da kötü değil. Her iki kare değişikliğini de birbiri ardına yaptığımız için, görünüm güncellenmez ve titremiyor.
Elbette içerik yüklenene kadar beklememiz gerekiyor, bu yüzden kodu -webViewDidFinishLoad:
delege yöntemine koyuyoruz .
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
}
Ben orada işaret etmelidir başka yaklaşım JavaScript kullanarak (teşekkürler @GregInYEG). Hangi çözümün daha iyi performans gösterdiğinden emin değilim.
İki hileli çözümden bunu daha çok seviyorum.
UIWebView
sizin ebeveyn görüşünüzden daha yüksekse, onu bir UIScrollView
.
Harika çalışan başka bir çözümüm var.
Bir yandan Ortwin'in yaklaşımı ve çözümü yalnızca iOS 6.0 ve sonraki sürümlerde çalışıyor, ancak iOS 5.0, 5.1 ve 5.1.1'de doğru çalışmıyor, diğer yandan sevmediğim ve anlayamadığım bir şey var. Ortwin'in yaklaşımıyla, yöntemin [webView sizeThatFits:CGSizeZero]
parametresiyle kullanılmasıdır CGSizeZero
: Bu yöntemler ve parametresi hakkında Apple Resmi belgelerini okursanız, açıkça şunu söyler:
Bu yöntemin varsayılan uygulaması, görünümün sınır dikdörtgeninin boyut bölümünü döndürür. Alt sınıflar, herhangi bir alt görünümün istenen düzenine göre özel bir değer döndürmek için bu yöntemi geçersiz kılabilir. Örneğin, bir UISwitch nesnesi, bir anahtar görünümünün standart boyutunu temsil eden sabit bir boyut değeri döndürür ve bir UIImageView nesnesi, o anda görüntülediği görüntünün boyutunu döndürür.
Demek istediğim, çözümüne herhangi bir mantık olmadan rastlamış gibi, çünkü dokümantasyonu okurken, iletilen parametre [webView sizeThatFits: ...]
en azından istenen değerlere sahip olmalı width
. Onun çözümü ile, istenen genişlik bir parametre ile webView
çağırmadan önce 'nin çerçevesine ayarlanır . Bu yüzden bu çözümün iOS 6'da "şans eseri" çalıştığını düşünüyorum.sizeThatFits
CGSizeZero
IOS 5.0 ve sonrası için çalışma avantajına sahip daha rasyonel bir yaklaşım hayal ettim ... Ve ayrıca birden fazla webView'un bulunduğu karmaşık durumlarda (Mülkünün webView.scrollView.scrollEnabled = NO
bir scrollView
.
Düzenini webView
istenen düzene zorlamak width
ve karşılık gelen height
seti webView
kendisine geri almak için kodum :
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;
}
Benim örnekte, o Not webView
özel bir gömülmüş scrollView
diğer sahip webViews
... Tüm bu webViews
onların vardı webView.scrollView.scrollEnabled = NO
ve ben eklenti zorunda kodunun son parçası hesaplanması oldu height
ait contentSize
benim geleneğin scrollView
bu gömme webViews
ama kolay gibiydi toplayarak olarak benim webView
's frame.size.height
hile ile hesaplanan yukarıda açıklanan ...
-[UIWebView scrollView]
yalnızca iOS 5.0 veya sonraki sürümlerde mevcuttur.
Ortwin'in cevabını çoğu zaman sadece işe yarayan bulduğum için bu soruyu yeniden canlandırıyorum ...
webViewDidFinishLoad
Yöntem birden çok kez çağrılabilir ve döndürdüğü ilk değer sizeThatFits
nihai boyutu ne olmalı sadece bazı kısmıdır. Sonra nedeni ne olursa olsun sonraki çağrısı için sizeThatFits
zaman webViewDidFinishLoad
yangınlar yine yanlış Daha önce yaptığı aynı değeri dönecektir! Bu, aynı içerik için bir tür eşzamanlılık sorunu gibi rastgele gerçekleşecek. Belki de bu davranış zamanla değişti, çünkü iOS 5 için geliştiriyorum ve bunun sizeToFit
da aynı şekilde çalıştığını buldum (daha önce böyle olmamasına rağmen?)
Bu basit çözüme karar verdim:
- (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):
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
}
}
Güncelleme: Yorumlarda belirtildiği gibi, içeriğin küçüldüğü durumu yakalayamadığını gördüm. Tüm içerik ve işletim sistemi sürümü için doğru olup olmadığından emin değil, bir deneyin.
webView.scalesPageToFit = YES
yukarıdaki yorumda belirtilen @Sijo gibi bir şey vermediğinizde çalışır .
Xcode 8 ve iOS 10'da bir web görünümünün yüksekliğini belirlemek için. kullanarak boy alabilirsin
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
CGFloat height = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
NSLog(@"Webview height is:: %f", height);
}
OR Swift için
func webViewDidFinishLoad(aWebView:UIWebView){
let height: Float = (aWebView.stringByEvaluatingJavaScriptFromString("document.body.scrollHeight")?.toFloat())!
print("Webview height is::\(height)")
}
Basit bir çözüm sadece kullanmak olabilir, webView.scrollView.contentSize
ancak bunun JavaScript ile çalışıp çalışmadığını bilmiyorum. Kullanılan JavaScript yoksa, bu kesinlikle işe yarar:
- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
CGSize contentSize = aWebView.scrollView.contentSize;
NSLog(@"webView contentSize: %@", NSStringFromCGSize(contentSize));
}
Bu tuhaf!
Ben çözümler test hem sizeThatFits:
ve [webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"]
edilmektedir DEĞİL benim için çalışıyor.
Ancak, web sayfası içeriğinin doğru yüksekliğini elde etmenin ilginç ve kolay bir yolunu buldum. Şu anda bunu temsilci yöntemimde kullandım scrollViewDidScroll:
.
CGFloat contentHeight = scrollView.contentSize.height - CGRectGetHeight(scrollView.frame);
İOS 9.3 Simülatör / Cihazda doğrulandı, iyi şanslar!
DÜZENLE:
Arka plan: html içeriği, dize değişkenim ve HTTP içerik şablonum tarafından hesaplanır loadHTMLString:baseURL:
, yöntemle yüklenir , burada kayıtlı JS komut dosyası yoktur.
Ben kullanıyorum UIWebView
bir Subview değildir (ve böylece pencere hiyerarşisinin parçası olmayan) için HTML içeriğinin boyutlarını belirlemek için bu UITableViewCells
. Bağlantısı kesilen kişinin UIWebView
boyutunu doğru şekilde bildirmediğini buldum -[UIWebView sizeThatFits:]
. Ek olarak, https://stackoverflow.com/a/3937599/9636'da belirtildiği gibi , uygun yüksekliği elde etmek için UIWebView
's' frame
height
yi 1'e ayarlamalısınız .
Eğer UIWebView
yüksekliği çok büyükse (yani 1000 olarak ayarladıysanız, ancak HTML içerik boyutu sadece 500 ise):
UIWebView.scrollView.contentSize.height
-[UIWebView stringByEvaluatingJavaScriptFromString:@"document.height"]
-[UIWebView sizeThatFits:]
Hepsi height
1000 döndürür .
Bu durumda sorunumu çözmek için , görev bilinciyle oyladığım https://stackoverflow.com/a/11770883/9636'yı kullandım . Ancak, bu çözümü yalnızca benim UIWebView.frame.width
. İle aynı olduğunda kullanırım -[UIWebView sizeThatFits:]
width
.
Buradaki önerilerin hiçbiri durumuma yardımcı olmadı, ancak bana cevap veren bir şey okudum. Sabit bir UI denetimleri kümesini takiben bir UIWebView olan bir ViewController'ım var. Tüm sayfanın, UI kontrolleri HTML içeriğine bağlıymış gibi kaydırılmasını istedim, bu yüzden UIWebView'da kaydırmayı devre dışı bıraktım ve ardından bir üst kaydırma görünümünün içerik boyutunu doğru şekilde ayarlamam gerekiyor.
Önemli ipucu, UIWebView'in ekrana işlenene kadar boyutunu doğru bir şekilde rapor etmemesidir. Bu yüzden içeriği yüklediğimde içerik boyutunu mevcut ekran yüksekliğine ayarlıyorum. Ardından, viewDidAppear'da kaydırma görünümünün içerik boyutunu doğru değere güncellerim. Yerel içerik için loadHTMLString'i çağırdığım için bu benim için çalıştı. LoadRequest kullanıyorsanız, html'nin ne kadar hızlı alındığına bağlı olarak webViewDidFinishLoad'daki contentSize'yi de güncellemeniz gerekebilir.
Titreşim olmaz, çünkü kaydırma görünümünün yalnızca görünmeyen kısmı değiştirilir.
webViewDidFinishLoad
Güvenli yaklaşıma güvenmeyi tercih ederim .
HTML'niz iframe'ler gibi ağır HTML içerikleri içeriyorsa (ör. Facebook-, twitter, instagram-embed'ler) gerçek çözüm çok daha zordur, önce HTML'nizi sarın:
[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>"];
Ardından , shouldStartLoadWithRequest öğenize x-update- webview -height -scheme işleme ekleyin :
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;
}
...
Ve son olarak aşağıdaki kodu layoutSubviews'ınıza ekleyin :
...
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 kodunuzun içinde zaman geciktirme (SetTimeout ve setInterval) uygulayabilirsiniz - bu size kalmış.
PSS UIWebView ve Facebook Yerleştirmeleri hakkında önemli bilgi: Gömülü Facebook gönderisi, UIWebView'da düzgün görünmüyor
Web görünümünü kaydırma görünümünde bir yerde alt görünüm olarak kullanırken, yükseklik sınırlamasını sabit bir değere ayarlayabilir ve daha sonra ondan çıkış yapabilir ve aşağıdaki gibi kullanabilirsiniz:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
webView.scrollView.scrollEnabled = NO;
_webViewHeight.constant = webView.scrollView.contentSize.height;
}
Ben de bu soruna takılı kaldım, sonra fark ettim ki webView'ın dinamik yüksekliğini hesaplamak istersem, önce webView genişliğini söylemem gerekiyor, bu yüzden js'den önce bir satır ekliyorum ve alabiliyorum çok doğru gerçek yükseklik.
Kod şu şekilde basit:
-(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;
//......
}
Xcode8 swift3.1:
webViewDidFinishLoad
Delegesi:let height = webView.scrollView.contentSize.height
Adım 1 olmadan, webview.height> gerçek contentHeight ise, 2. adım webview.height'ı döndürür, ancak contentize.height'ı döndürmez.
Ayrıca iOS 7'de belirtilen tüm yöntemlerin düzgün çalışması için bunu görünüm denetleyicisi viewDidLoad
yönteminize ekleyin :
if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) {
self.automaticallyAdjustsScrollViewInsets = NO;
}
Aksi takdirde hiçbir yöntem olması gerektiği gibi çalışmaz.