ListView von WebViews - die Wiederverwendung von Objekten unterschiedlicher Höhe schlägt fehl; fragt nach allen Ansichten, bevor sie angezeigt werden

8

Ich habe eine Aktivität, die ListView anzeigt. Jedes Element in ListView ist ein LinearLayout , das aus einem WebView besteht. Es gibt möglicherweise Hunderte von Elementen in der Liste und jede hat eine andere Höhe.

Das erste Problem ist, dass bei der Wiederverwendung einer wiederverwerteten Ansicht in getView() die neue Ansicht immer die Höhe der ursprünglichen Ansicht ist, obwohl ich layout_height sowohl für LinearLayout als auch für WebView festgelegt habe. zu wrap_content .

Das zweite Problem ist, dass getView() für jedes Element in der Liste aufgerufen wird, obwohl nur die ersten fünf oder sechs auf den Bildschirm passen. Ich habe das bei der Verwendung anderer Listenelementtypen nicht gesehen. Zum Beispiel, an einer anderen Stelle, ich eine Liste von benutzerdefinierten Ansichten, die alle die gleiche Höhe haben und ich sehe nur getView() für die Anzahl der Ansichten aufgerufen wird, die zunächst auf den Bildschirm passen.

Also ... Ich muss herausfinden, wie man recycled WebViews zum Rendern ihres neuen Inhalts erzwingt, so dass ihre Höhe berechnet werden kann, anstatt nur die vorherige Höhe zu verwenden. Und ich würde gerne wissen, warum das System mich in diesem Fall nach ALLEN meinen Artikeln fragt.

Hier sind die erforderlichen Code-Snippets:

%Vor%

Zeilen werden aus:

erstellt %Vor%

Dies ist getView () in meinem Adapter. HTML-Snippets stammen aus einer Reihe von Strings.

%Vor%     
Craig 27.01.2011, 17:07
quelle

4 Antworten

4

Ich denke, das Problem ist, dass das System mit dem Code, den Sie geschrieben haben, zunächst die Containerhöhe (Zeile linear_layout) und später den Inhalt (WebView) misst. Die zweite Kennzahl wirkt sich jedoch erst auf die erste aus, wenn Sie invalidate oder eine Methode aufrufen, mit der der Container seine Größe neu berechnet.

Warum Ihre getView-Methode mehrmals aufgerufen wird, überprüfen Sie die Methode getViewTypeCount () Ihres Adapters.

%Vor%

Dokumentation gibt Folgendes an:

  

"Diese Methode gibt die Anzahl von   Arten von Ansichten, die von erstellt werden   getView (int, Ansicht, Ansichtsgruppe). Jeder   type repräsentiert eine Reihe von Ansichten, die   kann in getView konvertiert werden (int, View,   ViewGroup). Wenn der Adapter immer   Gibt den gleichen Ansichtstyp für alle zurück   Elemente, sollte diese Methode 1 zurückgeben.   Diese Methode wird nur dann aufgerufen, wenn   Wenn der Adapter auf die eingestellt ist   AdapterView. "

Ich hatte ein Problem mit dieser Methode. Wenn eine große Zahl (wie 5000) meine App zum Absturz brachte, sieht es so aus, als ob sie intern für einige ListView-Berechnungen verwendet wird.

Hoffe es hilft irgendwie.

Übrigens, es gibt ein sehr gutes Gespräch über die Welt der ListViews

    
Axel M. Garcia 19.05.2011 10:35
quelle
3

Ich hatte das gleiche Problem mit meiner ExpandableListView. Von anderen Posts scheint es ein andauerndes Problem mit mehreren Webviews in einer Liste zu sein. Die Arbeit, die ich fand, war, wowViews beim ersten Aufruf von getView zu erstellen und zu gruppieren, und anschließend das webView im richtigen Index zurückzugeben. Es ist ein wenig mehr speicherintensiv, aber es verursacht keine Größenänderung.

%Vor%     
sirFunkenstine 13.08.2013 11:24
quelle
3

Ich habe die Lösung von sir Funzenstine ausprobiert, die großartig funktioniert. Nur der Client, für den ich diese App erstelle, hat die Leistung nicht gemocht. Und ich musste zugeben, dass es nicht so glatt war.

Es schien, dass die vorinstallierten WebViews hinzugefügt und entfernt wurden, wo das Problem lag. Die Benutzeroberfläche wurde jedes Mal für einen Sekundenbruchteil eingefroren, wenn die App das neue WebView für die nächste Zeile hinzugefügt / entfernt hat.

Lösung

Also dachte ich, es wäre besser, nur den Inhalt und die Höhe des WebView anzupassen, anstatt hinzuzufügen / zu entfernen. Auf diese Weise haben wir nur die Anzahl der WebViews, die momentan im Speicher sichtbar sind. Und wir können die Wiederverwendungsfunktionalität des ListView / Adapters verwenden.

Also habe ich ein einzelnes WebView hinter dem ListView hinzugefügt, das konstant die WebView-Höhe der nächsten Elemente berechnet. Sie können die Höhe mit der WebView-Methode getContentHeight ermitteln. Sie müssen dies in der onPageFinished-Methode tun, damit Sie die endgültige Höhe haben. Dies führte zu einem weiteren Problem, da die Methode null zurückgibt, wenn der Inhalt mit den Methoden loadDataWithBaseURL oder loadData geladen wird. Es scheint, dass der Wert schließlich gesetzt wird, aber noch nicht zu dem Zeitpunkt, zu dem der onPageFinished aufgerufen wird. Um dies zu umgehen, können Sie einen Thread hinzufügen, der ständig prüft, ob die getContentHeight nicht mehr 0 ist. Wenn es nicht Null ist, wird der Wert gesetzt und Sie können den nächsten laden.

Diese ganze Lösung ist ein bisschen hacky, aber sie hat mir einen schönen und flüssigen ListView mit WebViews mit verschiedenen Höhen gegeben.

Ein Beispielcode:

1: Legen Sie die Positionen der Zeilen fest, die Sie vorab laden möchten:

%Vor%

2: Starten Sie Runnable, um neue Elemente aus der Warteschlange zu laden und die Höhe eines Arrays zu überprüfen / hinzuzufügen:

%Vor%

3: Laden Sie neuen HTML-Inhalt und überprüfen Sie die Höhen:

%Vor%     
Ben Groot 14.11.2013 18:13
quelle
1

Meine Lösung (obwohl ich das Bounty aufstellte) für mein Problem war, das ImageView in ein FrameLayout zu legen, das dann intelligent wuchs.

Das Invalidieren der Ansicht oder das Erzwingen von Layoutberechnungen haben nichts für mich bewirkt, aber der Framelayout-Container für die Bildansicht schien alles zu lösen. Ich nehme an, dass dieses Verhalten in Fehler ist, aber die Problemumgehung war einfach genug.

Dasselbe gilt für das Webview des OP.

    
HaMMeReD 20.05.2011 22:11
quelle