Comment faire pour déterminer la taille du contenu d'un WKWebView?
Je suis expérimenter avec le remplacement d'un allouée dynamiquement instance de UIWebView avec un WKWebView exemple lors de l'exécution sous iOS 8 et plus récentes, et je ne peux pas trouver un moyen de déterminer la taille du contenu d'un WKWebView.
Ma vue web est intégré dans un plus grand UIScrollView conteneur, et donc j'ai besoin de déterminer la taille idéale pour l'affichage web. Cela me permettra de modifier son image pour montrer l'ensemble de son contenu HTML sans avoir besoin de faire défiler l'affichage web, et je vais être en mesure de régler la bonne hauteur pour le défilement de l'affichage du conteneur (par la mise en scrollview.contentSize).
J'ai essayé sizeToFit et sizeThatFits sans succès. Voici mon code qui crée un WKWebView instance et l'ajoute à la conteneur scrollview:
//self.view is a UIScrollView sized to something like 320.0 x 400.0.
CGRect wvFrame = CGRectMake(0, 0, self.view.frame.size.width, 100.0);
self.mWebView = [[[WKWebView alloc] initWithFrame:wvFrame] autorelease];
self.mWebView.navigationDelegate = self;
self.mWebView.scrollView.bounces = NO;
self.mWebView.scrollView.scrollEnabled = NO;
NSString *s = ... //Load s from a Core Data field.
[self.mWebView loadHTMLString:s baseURL:nil];
[self.view addSubview:self.mWebView];
Voici un expérimentales didFinishNavigation méthode:
- (void)webView:(WKWebView *)aWebView
didFinishNavigation:(WKNavigation *)aNavigation
{
CGRect wvFrame = aWebView.frame;
NSLog(@"original wvFrame: %@\n", NSStringFromCGRect(wvFrame));
[aWebView sizeToFit];
NSLog(@"wvFrame after sizeToFit: %@\n", NSStringFromCGRect(wvFrame));
wvFrame.size.height = 1.0;
aWebView.frame = wvFrame;
CGSize sz = [aWebView sizeThatFits:CGSizeZero];
NSLog(@"sizeThatFits A: %@\n", NSStringFromCGSize(sz));
sz = CGSizeMake(wvFrame.size.width, 0.0);
sz = [aWebView sizeThatFits:sz];
NSLog(@"sizeThatFits B: %@\n", NSStringFromCGSize(sz));
}
Et voici la sortie est généré:
2014-12-16 17:29:38.055 App[...] original wvFrame: {{0, 0}, {320, 100}}
2014-12-16 17:29:38.055 App[...] wvFrame after sizeToFit: {{0, 0}, {320, 100}}
2014-12-16 17:29:38.056 App[...] wvFrame after sizeThatFits A: {320, 1}
2014-12-16 17:29:38.056 App[...] wvFrame after sizeThatFits B: {320, 1}
La sizeToFit appel n'a aucun effet et sizeThatFits renvoie toujours à une hauteur de 1.
- Mise à jour: je suis toujours à la recherche d'une solution. Si je charge le contenu distant via [self.mWebView loadRequest:req]), la taille est disponible via l'auto.mWebView.le scrollView.contentSize à l'intérieur de didFinishNavigation. Mais si je charge mon contenu via [self.mWebView loadHTMLString:s], la taille n'est pas disponible jusqu'à ce que quelque temps plus tard. À l'aide de loadRequest avec un dataURL ne résout pas le problème. Et je ne sais pas quand "plus tard" est.
- Je me demande si il ne pourrait jamais être une réponse significative à cela? Considérer qu'à tout moment une page web peut de la taille de son contenu à la taille de sa fenêtre, alors comment pourrait-il en être que nous pourrions modifier la taille de la fenêtre à la taille de son contenu? Je pense qu'il y a une raison WKWebView ne fournit pas un intrinsicContentSize, il n'y a pas une seule significatif "intrinsèque" de la taille.
Vous devez vous connecter pour publier un commentaire.
Je pense que j'ai lu toute les réponses sur ce sujet et j'avais une partie de la solution. La plupart du temps j'ai passé à essayer de mettre en œuvre KVO méthode décrite par @davew, ce qui a parfois travaillé, mais la plupart du temps laissé un espace blanc sous le contenu d'un WKWebView conteneur. J'ai également implémenté @David Beck suggestion et fait de la hauteur du conteneur à 0 évitant ainsi la possibilité que le problème se produit si la hauteur du conteneur est plus grande que celle du contenu. Malgré que j'ai eu ce occasionnels espace vide.
Donc, pour moi, "contentSize" observateur avait beaucoup de défauts. Je n'ai pas beaucoup d'expérience avec les technologies web donc je ne peux pas répondre à ce qui était le problème avec cette solution, mais j'ai vu que si je n'avais hauteur d'impression dans la console, mais ne pas faire quelque chose avec elle (par exemple. redimensionner les contraintes), il accède à un certain nombre (par exemple, 5000) et va que pour le nombre avant que la plus haute (par exemple: 2500 - qui s'avère être la bonne). Si je dois définir la hauteur de la contrainte à la hauteur de qui je reçois de "contentSize" il définit lui-même pour le plus grand nombre il obtient et ne se met jamais redimensionnées à la bonne - qui est, encore une fois, mentionné par @David Beck commentaire.
Après beaucoup d'expériences que j'ai réussi à trouver une solution qui fonctionne pour moi:
Bien sûr, il est important de définir les contraintes correctement de sorte que le scrollView redimensionne en fonction de la containerHeight contrainte.
Comme il s'avère didFinish méthode de navigation n'est jamais appelé quand je voulais, mais ayant obtenu
document.readyState
étape, la suivante (document.body.offsetHeight
) est appelée au bon moment, en revenant à moi le bon numéro à la hauteur.document.body.scrollHeight
au lieu de cela, comme par ce gist et cette réponse.document.body.offsetHeight
oudocument.body.scrollHeight
à la fois à tord hauteurWKWebView
document.corps.offsetHeight renvoie mauvaise hauteur, aucune idée pourquoi? stackoverflow.com/questions/54187194/...-webkit-overflow-scrolling
etoverflow
dans le CSS du Web.completionHandler
dedocument.readyState
attend un long moment si le contenu de la page web est trop long, je préfère combiner cela avec @davew 's KVO solution.Vous pouvez utiliser la Clé-Valeur d'Observation (KVO)...
Dans votre ViewController:
Cela permettrait d'économiser l'utilisation de JavaScript et de vous garder dans la boucle sur tous les changements.
J'ai eu à traiter cette question de moi-même récemment. En fin de compte, j'ai été en utilisant une modification de la solution proposée par Chris McClenaghan.
En fait, sa solution originale est très bonne et il fonctionne dans la plupart des cas simples. Toutefois, elle n'a fonctionné pour moi sur des pages avec du texte. Probablement il travaille également sur des pages avec des images qui ont une hauteur statique. Cependant, il n'a certainement pas le travail quand vous avez des images dont la taille est définie avec
max-height
etmax-width
attributs.Et c'est parce que ces éléments peuvent obtenir redimensionné après la page est chargée. Donc, en fait, la hauteur retournée dans
onLoad
sera toujours correcte. Mais il n'est correcte que pour ce cas particulier. La solution de contournement consiste à surveiller le changement de labody
hauteur et d'y répondre.Surveiller le redimensionnement de la
document.body
Cette solution est de loin la plus élégante que je pouvais venir. Il ya, cependant, deux choses que vous devez être conscient de.
Tout d'abord, avant le chargement de votre URL, vous devez définir
shouldListenToResizeNotification
àfalse
. Cette logique supplémentaire est nécessaire pour les cas où le chargement de l'URL peut changer rapidement. Lorsque cela se produit, les notifications de l'ancien contenu pour quelque raison peut se chevauchent avec ceux du nouveau contenu. Pour empêcher un tel comportement, j'ai créé cette variable. Il assure qu'une fois que nous commençons à charger de nouveau contenu, nous n'avons plus le processus de notification de l'ancien et nous ne reprendre le traitement de redimensionner les notifications d'après le nouveau contenu est chargé.Plus important encore, cependant, vous devez être au courant à ce sujet:
Si vous adoptez cette solution, vous devez prendre en compte que si vous modifiez la taille de votre
WKWebView
à rien d'autre que la taille de la notification la notification sera déclenché à nouveau.Être prudent avec ce qu'il est facile d'entrer dans une boucle infinie. Par exemple, si vous décidez de gérer la notification par faire votre hauteur égale à signalé hauteur + quelques rembourrage supplémentaire:
Comme vous pouvez le voir, parce que je suis l'ajout de 8 à la hauteur, après ceci est fait la taille de mon
body
change et l'avis sera affiché à nouveau.Être attentifs à ces situations et sinon, vous devriez être bien.
Et s'il vous plaît laissez-moi savoir si vous découvrez un problème avec cette solution, je suis fier de moi-même si il est préférable de savoir si il y a des erreurs que je n'ai pas repéré!
meta viewport
tag set dewidth=device-width, initial-scale=1.0, shrink-to-fit=no
et j'ai supprimé la contrainte de l'installation sousshouldListenToResizeNotification = true
.shrink-to-fit=no
fixe ma question, merci!Essayez les solutions suivantes. Où que vous instanciez votre WKWebView exemple, d'ajouter quelque chose de semblable à la suivante:
Puis ajouter une méthode similaire à la suivante pour ce qui jamais de classe obéit WKScriptMessageHandler protocole pour gérer le message:
Cela fonctionne pour moi.
Si vous avez plus de texte dans votre document, vous pouvez avoir besoin d'envelopper le javascript comme ceci pour s'assurer que tout est chargé:
REMARQUE: Cette solution ne traite pas des mises à jour régulières du document.
userContentController:didReceiveScriptMessage:
je reçois un dictionnaire vide. 🙁document.width
etdocument.height
àwindow.innerWidth
etwindow.innerHeight
, c'est pourquoi vous avez été d'obtenir un dictionnaire vide, @TimurBernikowich.document.body.scrollHeight
a fonctionné pour moi d'obtenir une précision de la hauteur.document.height
etwindow.innerHeight
étaient tous les deux 0.window.onload=function () {...}
a également été nécessaire.Vous avez besoin d'attendre pour la webview à la fin du chargement. Voici un exemple que j'ai utilisé
WKWebView Contenu chargé de la fonction ne jamais être appelé
Puis après webview a fini de charger, ensuite, vous pouvez déterminer les hauteurs dont vous avez besoin en
Fonctionne pour moi
à l'aide de @Andriy la réponse de cette réponse j'ai été en mesure de définir obtenir la hauteur de contentSize dans WKWebView et en modifier la hauteur.
ici est plein de swift 4 code:
La plupart des réponses sont à l'aide du document".corps.offsetHeight".
Ce cache le dernier objet de l'organisme.
J'ai surmonté ce problème en utilisant un KVO observateur à l'écoute des changements dans WKWebview "contentSize", puis en exécutant ce code:
Ce n'est pas le personnage le plus de code possible, mais cela a fonctionné pour moi.
Vous pouvez également obtenu le contenu de la hauteur de WKWebView par evaluateJavaScript.
J'ai essayé de la faire défiler la vue KVO et j'ai essayé de l'évaluation de javascript sur le document, à l'aide de
clientHeight
,offsetHeight
, etc...Ce qui a fonctionné pour moi finalement est:
document.body.scrollHeight
. Ou utiliser lescrollHeight
de votre haut la plupart élément, par exemple un conteneurdiv
.J'écoute de la
loading
WKWebview des modifications de la propriété à l'aide de KVO:Et puis:
La
updateWebviewFrame
mise en œuvre:J'ai essayé la version Javascript dans UITableViewCell, et il fonctionne parfaitement. Toutefois, si vous voulez le mettre dans la scrollView. Je ne sais pas pourquoi, la hauteur peut être plus, mais on ne peut pas être plus courte. Cependant, j'ai trouvé une UIWebView solution ici. https://stackoverflow.com/a/48887971/5514452
Il travaille également dans WKWebView. Je pense que le problème est dû à la WebView besoin nouvelle disposition, mais de toute façon il ne rétrécit pas et ne peut l'agrandir. Nous avons besoin de réinitialiser la hauteur et il va certainement redimensionner.
Edit: j'ai réinitialisé la hauteur du cadre après la définition de la contrainte, parce que parfois, il ne va pas travailler pour cause de réglage de la hauteur du cadre à 0.
C'est une légère modification de @IvanMih de réponse. Pour ceux d'entre vous connaît un grand espace blanc à la fin de votre
WKWebview
cette solution a bien fonctionné pour moi:donc, fondamentalement, au lieu de calculer la hauteur en fonction de
scrollHeight
vous calculer la hauteur à l'aide dewebView.scrollView.contentSize
. Je suis sûr qu'il ya des scénarios où cela va casser, mais je pense que ça va le faire assez bien pour le contenu statique et si vous êtes à afficher tout le contenu sans avoir à faire défiler.Également essayé de mettre en œuvre les différentes méthodes et finalement venu à une solution. En conséquence, j'ai fait un auto-dimensionnement WKWebView, qui s'adapte à ses intrinsicContentSize à la taille de son contenu. De sorte que vous pouvez l'utiliser dans Automatique des Mises en page. Comme un exemple, j'ai fait un point de vue, qui pourrait vous aider à afficher formule math sur iOS apps: https://github.com/Mazorati/SVLatexView
Vous avez besoin pour ajouter du retard, son travail pour moi, au lieu de solutions avec JS ci-dessus:
Après beaucoup d'expériences que j'ai réussi à trouver une solution qui fonctionne pour moi, j'ai trouvé pour faire une webview hauteur dynamique sans l'aide de l'évaluation de javascript et aussi sans prendre de hauteur constante de webview ce travail avec moi comme un charme et aussi de travailler quand j'ai injecter un nouveau style pour HTML et de jouer avec les tailles de police et les hauteurs
code Swift
1 - donnez votre Webview de navigation délégué
2 - en délégation extension
espérons que cela fonctionne également avec vous les gars
** notez que ce n'est pas mon effort j'ai beaucoup cherché dans StackOverflow et d'autres sites et c'est ce qui fonctionne enfin avec moi, avec un grand nombre de tests aussi