Implementieren einer mehrspaltigen ListView mit unabhängigen Zeilenhöhen

8

Ich möchte eine Liste von etwa 200 ImageViews (zufällige Höhen) mit dem folgenden Layout in einer Collage erstellen:

Normalerweise würde ich dies in einem ListView für die Leistung machen, die ich mit Adaptern erhalte, aber da ich möchte, dass die Bilder in Spalten und mit unterschiedlicher Höhe angezeigt werden (Siehe Bild Beispiel ) abhängig von den Bildern kann ich zu diesem Zweck keine einzige Listenansicht verwenden.

Ich habe versucht, dieses Layout mit:

zu implementieren
  • Drei ListViews mit synchronem Scrolling = Langsam
  • Single ListView mit jeder Zeile, die drei Bilder enthält = unterschiedliche Höhen nicht zulassen
  • GridView = Verschiedene Höhen nicht zulassen
  • GridLayout = Schwer zu implementieren verschiedene Höhen programmgesteuert. Da kein Adapter vorhanden ist, sind OutOfMemoryErrors häufig
  • FlowLayout = Da kein Adapter vorhanden ist, sind OutOfMemoryErrors häufig
  • ScrollView mit drei Vertical LinearLayouts = Bisher beste Lösung, aber OutOfMemoryErrors sind üblich

Ich habe drei LinearLayouts in einer ScrollView verwendet, aber das ist alles andere als optimal. Ich würde lieber etwas mit einem Adapter verwenden.

BEARBEITEN Ich habe mir die StaggeredGridView angesehen, wie in einer Antwort unten, aber ich finde es ziemlich fehlerhaft. Gibt es stabilere Implementierungen?

    
DagW 29.12.2012, 18:07
quelle

6 Antworten

1

Ich denke, ich habe eine funktionierende Lösung für Sie.

Die hier erwähnten Hauptdateien befinden sich auch auf PasteBin in Ссылка

Ich habe im Grunde ein vereinfachtes Äquivalent des erwähnten github-Projekts implementiert, Ссылка , mit einer Reihe von exzellenten LoopJ SmartImageViews .

Meine Lösung ist bei weitem nicht so generisch und flexibel wie die StaggeredGridView , scheint aber gut und schnell zu funktionieren. Ein großer Unterschied funktional ist, dass wir die Bilder immer nur von links nach rechts, dann von links nach rechts wieder anordnen. Wir versuchen nicht, das nächste Bild in die kürzeste Spalte zu stellen. Dies macht die Unterseite der Ansicht ein wenig unebener, erzeugt jedoch weniger Verschiebung während der anfänglichen Belastung von der Bahn.

Es gibt drei Hauptklassen, eine benutzerdefinierte StagScrollView , die eine benutzerdefinierte StagLayout (untergeordnete Klasse FrameLayout ) enthält, die eine Gruppe von ImageInfo -Datenobjekten verwaltet.

Hier ist unser Layout , stag_layout.xml ( die anfängliche Höhe von 1000 dpi ist irrelevant, da sie im Code basierend auf den Bildgrößen neu berechnet wird ):

%Vor%

Hier ist unsere Aktivität onCreate , die das Layout verwendet. Die StagActivity sagt im Grunde nur die StagLayout welche URLs zu verwenden sind, wie groß der Abstand zwischen jedem Bild sein soll und wie viele Spalten es gibt. Für mehr Modularität hätten wir diese Parameter an die StagScrollView übergeben können (die das StagLayout enthält, aber die Bildlaufansicht hätte sie sowieso nur durch das Layout führen müssen):

%Vor%

Bevor wir zu der Lösung kommen, ist hier unsere einfache StagScrollView Unterklasse. Sein einziges spezielles Verhalten ist es, seinem Hauptkind (unserem StagLayout ) zu sagen, welches der aktuell sichtbare Bereich ist, damit er die kleinstmögliche Anzahl von realisierten Untersichten effizient nutzen kann.

%Vor%

Hier ist dann die wichtigste Klasse StagLayout .

Zuerst richtet setUrls unsere Datenstrukturen ein.

%Vor%

Unsere Hauptdatenstruktur ist ImageInfo . Es ist eine Art leichter Platzhalter, mit dem wir verfolgen können, wo jedes Bild angezeigt wird, wenn es sein muss. Wenn wir unsere untergeordneten Ansichten planen, verwenden wir die Informationen in ImageInfo, um herauszufinden, wo die tatsächliche Ansicht platziert werden soll. Eine gute Möglichkeit, über ImageInfo nachzudenken, ist eine "virtuelle Bildansicht".

Siehe inline für Details.

%Vor%

Der Rest der Magie passiert in StagLayout's onMeasure und onLayout .

%Vor%

Ok, jetzt sehen wir, wie wir alle ImageInfos organisieren.

%Vor%

Und jetzt sehen wir, wie wir reale SmartImageViews während onLayout erstellen, wiederverwenden und entsorgen.

%Vor%

Denken Sie daran, dass _viewportTop und _viewportBottom bei jedem Scrollen des Benutzers festgelegt werden.

%Vor%     
Morgan 08.01.2013, 19:47
quelle
1

Sie können sich Ссылка

ansehen

Ich habe nicht persönlich daran gearbeitet, aber Sie könnten zumindest einige Konzepte stehlen.

    
Abhinav Manchanda 29.12.2012 18:38
quelle
0
  1. Erstellen Sie eine Listenansicht in einem Layout.
  2. Erstellen Sie ein anderes Layout mit dem gleichen Hintergrund wie das Listenansichts-Hintergrundlayout mit drei Bildansichten (nebeneinander, dh rechts von einander), deren Eigenschaften horizontal auf Wrap_Content gesetzt sind, und die gesamten Ansichten-Eigenschaften, in denen Bildsichten liegen an Wrap_Content.
  3. Füllen Sie das Layout in der Methode getview () des Listenansichtsadapters auf. In diesem müssen Sie 3 Bildsätze in Bildansichten des überhöhten Layouts einstellen.

Hoffe, das hilft!

    
Guri Jagat 05.01.2013 08:07
quelle
0

Ich denke, es kann mit drei unabhängigen Listenansicht implementiert werden, nur was Sie tun müssen, um Layout für Bildansicht aufzublasen und es zu Listview hinzuzufügen.

Verwenden Sie folgende Parameter als Layout beim Aufpumpen.

Layoutbreite: match_parent Layout Höhe: wrap_content Sie können das Layoutgewicht als .3 für alle drei Listenansichten mit layout_width als 0dp und Höhe als fill_parent zuweisen.

hoffe das hilft.

    
Techfist 08.01.2013 05:47
quelle
0

Können Sie Ihre aktuelle Lösung nicht in einer benutzerdefinierten Liste verwenden?

in der getView-Methode für jede Zeile pumpen Sie Ihre vorhandene Lösung auf (converview ofcourse prüfen) d. h. ScrollView mit drei Vertical LinearLayouts.

    
android2013 08.01.2013 10:37
quelle
0

Weißt du, warum die 3-List-View-Lösung langsam war?

Wie viele verschiedene Größen gibt es in jeder Spalte? Ich denke, dass Sie für die effiziente Wiederverwendung von Ansichten einen Ansichtstyp für jede Bildgröße erstellen und dann sicherstellen sollten, dass Sie getItemViewType , um sicherzustellen, dass Sie den richtigen Ansichtstyp recyceln. Sonst werden Sie vom Recycling nicht viel profitieren. Sie möchten nur die Quelle für die Bildansicht zurücksetzen können.

    
ndw 08.01.2013 16:02
quelle

Tags und Links