WebView > Größe des Inhaltes

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • WebView > Größe des Inhaltes

    Hallo,

    natürlich habe ich schon die Suche bemüht, aber klüger bin ich noch nicht… ;)

    Ich möchte die Größe der Aufgerufenen Seite in einem WebView, so dass nicht gescrollt werden muss.
    Mit meinem Code funktioniert das, aber nicht für alle Seiten.

    Code siehe unten…

    Hat da jemand nen Plan von? Danke.

    Viele Grüße

    Quellcode

    1. // …
    2. WebView *webView = self;
    3. if(webView == nil)
    4. {
    5. return NSZeroSize;
    6. }
    7. // …
    8. WebFrame *webFrame = [webView mainFrame];
    9. if(webFrame == nil)
    10. {
    11. return NSZeroSize;
    12. }
    13. // …
    14. WebFrameView *webFrameView = [webFrame frameView];
    15. if(webFrameView == nil)
    16. {
    17. return NSZeroSize;
    18. }
    19. // …
    20. NSView *view = [webFrameView documentView];
    21. if(view == nil)
    22. {
    23. return NSZeroSize;
    24. }
    25. // …
    26. NSRect rect = [view frame];
    27. // …
    28. NSSize size = rect.size;
    29. // …
    30. return size;
    31. // …
    Alles anzeigen
  • So…

    Ich weiß die Ursache und die "Lösung":

    Es gibt Websiten, wie z.B. bei meinen, die ordnen den gesamten Inhalt horizontal/vertikal mittig an.
    Das lässt sich im CSS entsprechend steuern position absolute, left, right, margin-top etc.

    Wird das WebView in ein Fenster eingesetzt, dann verändert sich das ScrollView permanent beim Ziehen.
    Deshalb kommt über -documentView nur zu vielleicht 90% aller Fälle an die gesamte Größe der Website.

    Mit einer Schleife kann man die Scroller abfragen und sich an die echte Größe rantasten.
    Das ist eigentlich unschön, aber es funktioniert immer.

    Auch mit dem Forum hier bekommt man die richtige Größe ;)

    Viele Grüße

    Quellcode

    1. -(BOOL)wp_isHorizontalScrollerVisible
    2. {
    3. // …
    4. NSScrollView *scrollView = [self wp_documentScrollView];
    5. if(scrollView == nil)
    6. {
    7. return NO;
    8. }
    9. // …
    10. NSScroller *scroller = [scrollView horizontalScroller];
    11. if(scroller == nil)
    12. {
    13. return NO;
    14. }
    15. // …
    16. CGFloat x = [scroller knobProportion];
    17. if(x > 0.97)
    18. {
    19. return NO;
    20. }
    21. // …
    22. return YES;
    23. // …
    24. }
    25. -(BOOL)wp_isVerticalScrollerVisible
    26. {
    27. // …
    28. NSScrollView *scrollView = [self wp_documentScrollView];
    29. if(scrollView == nil)
    30. {
    31. return NO;
    32. }
    33. // …
    34. NSScroller *scroller = [scrollView verticalScroller];
    35. if(scroller == nil)
    36. {
    37. return NO;
    38. }
    39. // …
    40. CGFloat x = [scroller knobProportion];
    41. if(x > 0.97)
    42. {
    43. return NO;
    44. }
    45. // …
    46. return YES;
    47. // …
    48. }
    49. -(BOOL)wp_sizeToFit
    50. {
    51. // …
    52. WebView *webView = self;
    53. if(webView == nil)
    54. {
    55. return NO;
    56. }
    57. // …
    58. NSRect rect = [webView frame];
    59. NSSize size = rect.size;
    60. // …
    61. while(webView != nil)
    62. {
    63. // …
    64. if([self wp_isHorizontalScrollerVisible] == YES)
    65. {
    66. size.width = size.width + 10.0;
    67. }
    68. // …
    69. if([self wp_isVerticalScrollerVisible] == YES)
    70. {
    71. size.height = size.height + 10.0;
    72. }
    73. // …
    74. NSLog(@"%@", NSStringFromSize(size));
    75. // …
    76. [webView setFrameSize:size];
    77. // …
    78. if([self wp_isHorizontalScrollerVisible] == YES)
    79. {
    80. continue;
    81. }
    82. // …
    83. if([self wp_isVerticalScrollerVisible] == YES)
    84. {
    85. continue;
    86. }
    87. // …
    88. break;
    89. // …
    90. }
    91. // …
    92. size.width = size.width * 1.05;
    93. size.height = size.height * 1.05;
    94. // …
    95. [webView setFrameSize:size];
    96. // …
    97. return YES;
    98. // …
    99. }
    Alles anzeigen
  • little_pixel schrieb:

    Mit einer Schleife kann man die Scroller abfragen und sich an die echte Größe rantasten.
    Das ist eigentlich unschön, aber es funktioniert immer.

    Das ist nicht nur eigentlich unschön. Bitte mach' so etwas nicht. Ich wäre wahrscheinlich einer von denen, der dir aus reiner Gehässigkeit ein <html style="width:110%; height:110%"> ins Programm wirft und zusieht, wie es sich quält.

    Es gibt halt Seiten (auch statische), die sich schlicht weigern, sich ohne Scroller darstellen zu lassen. Für alle anderen sollte dein eingangs beschriebener Weg (webview.mainFrame.frameView.documentView.frame.size) eigentlich ganz gut funktionieren. Das Ergebnis ist aber abhängig von der ursprünglichen Größe des Webviews - der Layout-reflow basiert auf der ursprünglichen Fensterbreite. Kannst du mal Seiten nennen (gutartige - also statisch, ohne JS, Nachladen, CSS außerhalb von Box-Bounds usw), bei denen das nicht ging? Ich kenne nur einige, die onload noch etwas nachziehen (z.B. Heise) - die kann man daran erkennen, dass nach dem didLoad des Hauptframes noch weitere Frames oder Ressourcen reinkommen. Wenn man denen das JS abdreht sollte das aber eigentlich auch gehen.
    Multigrad - 360°-Produktfotografie für den Mac
  • Hallo,

    Das ist nicht nur eigentlich unschön. Bitte mach' so etwas nicht. Ich wäre wahrscheinlich einer von denen, der dir aus reiner Gehässigkeit ein <html style="width:110%; height:110%"> ins Programm wirft und zusieht, wie es sich quält.

    Ich finde die Lösung auch nicht gut, aber die Sache ist ziemlich verzwickt.
    Das mit der 110% Breite/Höhe habe ich bei mir im Code abgefangen, da ich beim Test schon reingelaufen bin.

    Schau mal hier.

    Mh… :(

    Ich habe mal ein Testprojekt erstellt und hole mir ordnungsgemäß die Größe via -documentView.
    Zum Test habe ich mal meine Seite eingebunden, da diese zufälligerweise genau das Problem zeigt.

    - App öffnen
    - warten bis der Inhalt geladen ist
    - der vertikale Scrollbalken ist sichtbar
    - der obere Inhalt der Website ist nicht sichtbar und wird abgeschnitten
    - mal ein Blick auf das zweite Textfeld werfen, Größe des Inhaltes des WebViews
    - Fenster langsam aufziehen
    - Inhalt wird irgendwann super gezeigt und die Scroller verschwinden
    - das ist dann die perfekte Größe
    - Ausgabe der Größe ist aber immer permanent dynamisch

    Woher weiß das ScrollView/WebView bzw. Apple, dass sie die Scrollbalken zeigen müssen?
    Den da ist es ja immer richtig. Auch bei anderen Webseiten…

    Viele Grüße
    Dateien
  • Ich habe eine Idee:

    Alle Elemente unter -body abholen und rekursiv durchlaufen.
    Ich hoffe dann kommt man an die Bounding-Boxen. Somit ließe sich ein Offset ermitteln.
    Wenn dieser sich immer mehr verkleinert beim Verändern des WebViews, dann kann irgendwann der gesamte Inhalt gezeigt werden und man hätte die Größe.

    Das teste ich jetzt mal…

    Viele Grüße
  • Ich befürchte, dass das auch nicht funktionieren wird. Was du willst lässt sich nicht realisieren, zumindest nicht einfach und allgemein. WebKit gibt schon die richtige Seitengröße nach der Spezifikation aus - das Dumme ist, dass diese fast beliebig von der Fenstergröße abhängen kann (sprich: Niemand sagt, dass bei dieser Fenstergröße alles passt - denn daraufhin kann sich das Dokumentlayout wieder komplett ändern). Es ist einfach zu entscheiden, ob für eine bestimmte Konfiguration Scrollbalken gemalt werden müssen oder nicht (testen, ob Nicht-Hintergrund außerhalb des sichtbaren Bereichs gemalt wird), aber es ist schwer bis unmöglich zu berechenen, ob es irgend eine Größe gibt, in der keine Scrollbalken benötigt werden (und falls ja, welche Größe das ist).

    Nimm folgendes Beispiel:

    Quellcode

    1. <body>
    2. <div style="position:absolute; top:0px; left:0px; height:100px; width:-webkit-calc(150% - 500px); background-color:blue;"></div>
    3. <div style="position:absolute; top:100px; left:0px; height:100px; width:-webkit-calc(70% + 250px); background-color:red;"></div>
    4. </body>

    Der blaue Balken wächst schneller als die Fensterbreite, der rote langsamer. Dadurch ergibt sich nur ein kleiner Breitenbereich, in dem keine Scrollbalken benötigt werden - bei kleineren sorgt der rote Balken, bei größeren der blaue dafür, dass man scrollen kann. Für die meisten Fälle reicht die Größenangabe von Webkit, vielleicht kann man einige andere Fälle durch Tricksereien abdecken. Aber für einige wird's schwierig, selbst wenn man Zugriff auf tiefere Ebenen der Rendering Engine hätte (ggf. über einen Constraint solver, aber spätestens wenn weitere Operatoren für CSS3 calc eingeführt werden wird das auch ein Krampf).

    Musst du das unbedingt für beliebige Websites machen? Bei deiner Seite ließe sich das recht einfach lösen, indem man die horizontale Positionierung über margin:auto macht und eine min-height angibt (oder ggf. einen anderen Mechanismus zum vertikalen Zentrieren verwendet). Kannst du nicht auf die Sonderfälle pfeifen? Falls das nicht geht, würde ich eher versuchen, eine feste Ausgangsgröße zu wählen, dafür das Layout zu machen und zu fixieren, anschließend die Bounds aller Inhalte zusammenzuführen (was nicht unbedingt die Größe sein muss) und dann den gesamten Inhalt (also auch das, was außerhalb der Bounds liegt) in einen View zu rendern ohne das Layout erneut anzustoßen. Keine Ahnung ob das geht, aber ich bin mir ziemlich sicher, dass der andere Weg kein erfolgversprechender ist.
    Multigrad - 360°-Produktfotografie für den Mac
  • Vielen Dank für die Antwort!

    Musst du das unbedingt für beliebige Websites machen?

    Ja, der Anwender kann eine beliebige URL auf die Anwendung ziehen…

    In der Tat habe ich jetzt aber eine sehr gute Lösung:

    - WebView frame zu NSZeroRect setzen
    - mainFrame, documentView, Größe abholen und Höhe auf 0 setzen (aber noch nichts weiter machen)
    - DOMDocument, alle Unterelemente und nach negativem Extrema X der Bounding-Box suchen
    - wenn der Extrema X kleiner 0 ist positiv zu der Größe dazu addieren
    - WebView setzen (Höhe ist 0 und nur die Breite ist gegeben)
    - DOMDocument, alle Unterelemente und nach negativem Extrema Y der Bounding-Box suchen
    - wenn der Extrema Y kleiner 0 ist positiv zu der Größe dazu addieren
    - WebView setzen (Höhe und Breite ist nun gegeben)

    Ich habe jetzt unzählige Websiten durch und es funktioniert immer.
    Das scheint mir ein sauberer Weg zu sein, da es nicht über die GUI (Scrollbalken) funktioniert.

    Sicherlich gibt es einige Sonderfälle, bei denen es vielleicht nicht korrekt funktioniert, aber dann ist das halt so.
    Dennoch ist der Gewinn über nur -documentView enorm.

    Viele Grüße