Frage

Zusammenfassung: Versuchen Sie, eine ListView über einen benutzerdefinierten Adapter -Wrapper dynamisch zu Kopfzeilen hinzuzufügen. ListView hat Probleme, die Bildlaufposition synchron zu halten. Runnable Demo -Projekt zur Verfügung gestellt.

Ich möchte eine Liste dynamisch zu einer Liste hinzufügen, die auf den Werten in einem Cursoradapter basiert, mehrere Positionen vor dem, was der Benutzer derzeit anzeigt. Dazu habe ich einen Adapter, der den Cursoradapter umhüllt und den neuen Inhalt in einem Sparsarray indexiert. Der ListView muss aktualisiert werden, wenn Elemente zum benutzerdefinierten Adapter hinzugefügt werden, aber ich habe viele Fallstricke getroffen, um dies zu arbeiten, und würde einige Ratschläge lieben.

Das Demo -Projekt kann hier heruntergeladen werden: DynamicsEctionedList.zip

In der Demo werden die Überschriften dynamisch hinzugefügt, indem 10 Plätze gesucht werden, um die richtige Position zu finden, in der die Listelemente zum nächsten Buchstaben wechseln. Jede Implementierung von notifyDataSchanged hat Probleme wie beschrieben:

Demo 1Diese Demo zeigt die Bedeutung von meldenDataSchanged (). Wenn Sie auf irgendetwas klicken, stürzt die App ab. Dies liegt an einigen Gesundheitsprüfungen in ListView ... mItemCount != adapter.getItemCount(). Moral ist, wir müssen die Liste mitteilen, dass sich die Daten geändert haben.

Demo 2Der natürliche nächste Schritt besteht darin, die Liste der Änderungen bei Änderungen zu informieren. Leider bricht das Scrollen der ListView die Interaktion, bis die App den Berührungsmodus herausschaltet. Sie müssen weit genug "Schriftrolle fling", um neue Überschriften zu generieren, um dies zu bemerken. Wenn Sie auf den Bildschirm tippen, wird die Schriftrolle nicht gestoppt, und sobald keiner der Listenelemente anklickbar ist. Dies liegt an einigen if (!mDataChanged) { /* do very important stuff */ } Code in AbslistView.ontouchEvent ().

Demo 3Um dies zu beheben, führt Demo 3 ein anstehendes Flag ein und der benutzerdefinierte Adapter erhält eine NotifyDataTaChangeDifNeeded (), die von der ListView aufgerufen werden kann, sobald er einen "sicheren" Status für Änderungen eingegeben hat. Der erste Punkt, an dem Änderungen benachrichtigt werden müssen, finden Sie in listView.layoutchildren (). Daher habe ich diese Methode überschrieben, um zuerst Änderungen bei Bedarf zu informieren, und rufen Sie dann auf. Klicken Sie dann auf ein Listenelement vorbei.

Das funktioniert nicht ganz richtig, obwohl ich mir nicht ganz sicher bin, warum. Durch das Tippen oder Auswahl eines Elements mit Tastatur/Trackball wird die Liste aktualisiert, ohne die alte Position ordnungsgemäß zu synchronisieren. Es scrollt nach oben auf der Liste, die nicht akzeptabel ist.

Demo 4Das Bildlaufproblem in Demo 3 kann zumindest im Touch -Modus erobert werden. Durch Hinzufügen eines Aufrufs zum BenachrichtigenDatasetchangedifNeeded () nach Touch Down findet die Datenänderung zu einem solchen Zeitpunkt statt, in dem alle Berührungsinteraktion wie erwartet funktionieren und die Listenposition ordnungsgemäß synchronisiert wird.

Ich kann jedoch kein Analog dafür finden, wenn das Gerät nicht im Touch -Modus ist, ganz zu schweigen von der Tatsache, dass es definitiv wie ein Hack erscheint. Die Liste scrollt fast immer nach oben zurück. Ich kann nicht herausfinden, was dazu führt, dass sie gelegentlich die richtige Position beibehält.

Da Android mich bei jedem Schritt des Weges kämpft, denke ich, dass es einen besseren Ansatz geben sollte. Bitte versuchen Sie die Demo, wenn Korrekturen angewendet werden können, um sie zum Laufen zu bringen, wäre das großartig!

Vielen Dank an alle, die dies untersuchen können, hoffentlich, wenn wir den Code zum Laufen bringen können, wird er für andere nützlich sein, die versuchen, dieselbe Optimierung für Listen mit Überschriften zu erreichen.

War es hilfreich?

Lösung

Das Hauptproblem mit dem oben dargestellten Ansatz bestand darin, dass der Datensatz direkt aus dem von den Superklassen ausgeführten Code geändert wurde. Durch die Bevölkerung der Überschriften in GetView () habe ich die Daten in der Mitte eines Betriebs oder in einem "unsicheren" Zustand in den Superklassen geändert. Aus diesem Grund brach alle Touch -Interaktionen, als OnnotifyDatasetanged während einer Schriftrolle aufgerufen wurde. Die Daten müssen von einer externen Quelle hinzugefügt werden, nicht aus den Adaptermethoden.

Dies kann durch Verwendung eines Handlers oder Asynctasks erfolgen, um die Überschriften zum Adapter hinzuzufügen und seine NotifyDataSchanged aufzurufen. Diese werden auf einem UI -Thread ausgeführt und stören nicht den Superklassenzustand. Vielen Dank an das endlosen Beispiel für das EndlessAdapter für die Einführung des Konzepts eines Asynctasks zum Hinzufügen von Daten zu einer Liste.

Die OnTouchEvent () und Layoutchildren () Hacks wurden nach dieser Änderung nicht mehr benötigt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top