Ich möchte meine Header-Ansichten oben auf dem Bildschirm wie im Bild unten korrigieren, ohne externe Bibliotheken zu verwenden.
In meinem Fall möchte ich es nicht alphabetisch machen. Ich habe zwei verschiedene Arten von Ansichten (Header und Normal). Ich möchte nur den letzten Header an der Spitze fixieren.
android
header
android-recyclerview
sticky
Jaume Colom
quelle
quelle
Antworten:
Hier werde ich erklären, wie es ohne eine externe Bibliothek geht. Es wird ein sehr langer Beitrag, also machen Sie sich bereit.
Lassen Sie mich zunächst @ tim.paetz bestätigen, dessen Beitrag mich dazu inspiriert hat, meine eigenen Sticky-Header mit
ItemDecoration
s zu implementieren . Ich habe einige Teile seines Codes in meiner Implementierung ausgeliehen.Wie Sie vielleicht schon erlebt, wenn Sie es selbst zu tun versucht, ist es sehr schwer , eine gute Erklärung zu finden , WIE es tatsächlich zu tun mit der
ItemDecoration
Technik. Ich meine, was sind die Schritte? Was ist die Logik dahinter? Wie kann ich den Header ganz oben auf der Liste platzieren? Wenn Sie keine Antworten auf diese Fragen kennen, können andere externe Bibliotheken verwenden, während Sie dies selbst tunItemDecoration
ziemlich einfach ist .Anfangsbedingungen
list
aus Elementen unterschiedlichen Typs bestehen (nicht im Sinne von "Java-Typen", sondern im Sinne von "Header / Element" -Typen).list
muss ein Kopfelement sein.Hier gebe ich den vollständigen Code für meinen
RecyclerView.ItemDecoration
Anruf anHeaderItemDecoration
. Dann erkläre ich die Schritte im Detail.Geschäftslogik
Also, wie mache ich es kleben?
Das tust du nicht. Sie können einen
RecyclerView
Artikel Ihrer Wahl nicht einfach anhalten und oben bleiben, es sei denn, Sie sind ein Guru für benutzerdefinierte Layouts und kennen mehr als 12.000 CodezeilenRecyclerView
auswendig. Also, wie es immer mit dem UI-Design geht, wenn Sie etwas nicht machen können, fälschen Sie es. Sie zeichnen einfach den Header über alles mitCanvas
. Sie sollten auch wissen, welche Elemente der Benutzer im Moment sehen kann. Es kommt einfach vor, dassItemDecoration
Sie sowohlCanvas
Informationen als auch Informationen zu sichtbaren Elementen erhalten. Hier sind die grundlegenden Schritte:Bei der
onDrawOver
MethodeRecyclerView.ItemDecoration
erhalten Sie das allererste (oberste) Element, das für den Benutzer sichtbar ist.Bestimmen Sie, welcher Header es darstellt.
Zeichnen Sie mit der
drawHeader()
Methode den entsprechenden Header über die RecyclerView .Ich möchte auch das Verhalten implementieren, wenn der neue kommende Header auf den obersten trifft: Es sollte so aussehen, als würde der bevorstehende Header den obersten aktuellen Header sanft aus der Ansicht schieben und schließlich seinen Platz einnehmen.
Hier gilt die gleiche Technik des "Zeichnens auf alles".
Bestimmen Sie, wann der oberste "feststeckende" Header auf den neuen anstehenden Header trifft.
Holen Sie sich diesen Kontaktpunkt (das ist die Unterseite des von Ihnen gezeichneten klebrigen Headers und die Oberseite des bevorstehenden Headers).
Wenn das Element in der Liste diesen "Kontaktpunkt" betritt, zeichnen Sie Ihren klebrigen Header neu, sodass sich seine Unterseite oben auf dem Element befindet. Dies erreichen Sie mit der
translate()
Methode derCanvas
. Infolgedessen befindet sich der Startpunkt des oberen Headers außerhalb des sichtbaren Bereichs und scheint "vom kommenden Header herausgeschoben" zu werden. Wenn es vollständig verschwunden ist, zeichnen Sie den neuen Header oben.Der Rest wird durch Kommentare und ausführliche Anmerkungen in dem von mir bereitgestellten Code erklärt.
Die Verwendung ist unkompliziert:
Sie
mAdapter
müssen implementierenStickyHeaderInterface
damit es funktioniert. Die Implementierung hängt von Ihren Daten ab.Schließlich stelle ich hier ein GIF mit halbtransparenten Überschriften zur Verfügung, damit Sie die Idee erfassen und tatsächlich sehen können, was unter der Haube vor sich geht.
Hier ist die Illustration des Konzepts "Einfach auf alles zeichnen". Sie können sehen, dass es zwei Elemente "Kopfzeile 1" gibt - eines, das wir zeichnen und in einer festgefahrenen Position oben bleiben, und das andere, das aus dem Datensatz stammt und sich mit allen anderen Elementen bewegt. Der Benutzer wird das Innenleben nicht sehen, da Sie keine halbtransparenten Überschriften haben.
Und hier, was passiert in der "Push-out" -Phase:
Hoffe es hat geholfen.
Bearbeiten
Hier ist meine tatsächliche Implementierung der
getHeaderPositionForItem()
Methode im RecyclerView-Adapter:Etwas andere Implementierung in Kotlin
quelle
private View getHeaderViewForItem(int itemPosition, RecyclerView parent) { int headerPosition = mListener.getHeaderPositionForItem(itemPosition); if(headerPosition != mCurrentHeaderIndex) { mCurrentHeader = mListener.createHeaderView(headerPosition, parent); mCurrentHeaderIndex = headerPosition; } return mCurrentHeader; }
Am einfachsten ist es, einfach eine Artikeldekoration für Ihre RecyclerView zu erstellen.
}}
XML für Ihren Header in recycler_section_header.xml:
Und schließlich, um die Artikeldekoration zu Ihrer RecyclerView hinzuzufügen:
Mit dieser Artikeldekoration können Sie den Header beim Erstellen der Artikeldekoration entweder mit einem Booleschen Wert fixieren / kleben oder nicht.
Ein vollständiges Arbeitsbeispiel finden Sie auf github: https://github.com/paetztm/recycler_view_headers
quelle
wrap_content
), diese auchfixLayoutSize
nach dem Festlegen des Titeltextes ausführen möchten .Ich habe oben meine eigene Variation von Sevastyans Lösung gemacht
... und hier ist die Implementierung von StickyHeaderInterface (ich habe es direkt im Recycler-Adapter gemacht):
In diesem Fall wird der Header also nicht nur auf Leinwand gezeichnet, sondern mit Selektor oder Ripple, Clicklistener usw. angezeigt.
quelle
recyclerView.addItemDecoration(HeaderItemDecoration(recyclerView, adapter))
. Leider kann ich kein Beispiel für eine Implementierung finden, die ich verwendet habe. Ich habe die Antwort bearbeitet - Text zu Kommentaren hinzugefügtan alle, die nach einer Lösung für das flackernde / blinkende Problem suchen, wenn Sie dies bereits getan haben
DividerItemDecoration
. Ich scheine es so gelöst zu haben:Das scheint zu funktionieren, aber kann jemand bestätigen, dass ich nichts anderes kaputt gemacht habe?
quelle
Sie können die Implementierung der Klasse
StickyHeaderHelper
in meinem FlexibleAdapter überprüfen und übernehmen Projekt und an Ihren Anwendungsfall anpassen.Ich empfehle jedoch, die Bibliothek zu verwenden, da sie die Art und Weise vereinfacht und neu organisiert, wie Sie normalerweise die Adapter für RecyclerView implementieren: Erfinden Sie das Rad nicht neu.
Ich würde auch sagen, verwenden Sie keine Decorators oder veralteten Bibliotheken und verwenden Sie keine Bibliotheken, die nur 1 oder 3 Dinge tun. Sie müssen die Implementierungen anderer Bibliotheken selbst zusammenführen.
quelle
Decorator
s?Eine weitere Lösung, die auf dem Scroll Listener basiert. Die Anfangsbedingungen sind die gleichen wie in der Antwort von Sevastyan
Layout für ViewHolder und Sticky Header.
item_header.xml
Layout für RecyclerView
Klasse für HeaderItem.
Es ist alles nützlich. Die Implementierung des Adapters ViewHolder und anderer Dinge ist für uns nicht interessant.
Schnittstelle für die Bindungskopfansicht.
quelle
for (int i = position; position >= 0; i--){ //should be i >= 0
Yo,
So machen Sie es, wenn Sie nur eine Art von Halter-Stick möchten, wenn dieser aus dem Bildschirm herauskommt (wir kümmern uns nicht um Abschnitte). Es gibt nur einen Weg, ohne die interne RecyclerView-Logik des Recyclings von Elementen zu brechen, nämlich die zusätzliche Ansicht über dem Header-Element von recyclerView aufzublasen und Daten an dieses zu übergeben. Ich werde den Code sprechen lassen.
Und dann machen Sie das einfach in Ihrem Adapter:
Wobei YOUR_STICKY_VIEW_HOLDER_TYPE viewType Ihres angeblich klebrigen Halters ist.
quelle
Für diejenigen, die sich Sorgen machen können. Basierend auf Sevastyans Antwort, sollten Sie es horizontal scrollen lassen wollen. Ändern Sie einfach alle
getBottom()
zugetRight()
undgetTop()
zugetLeft()
quelle
Die Antwort war bereits hier. Wenn Sie keine Bibliothek verwenden möchten, können Sie die folgenden Schritte ausführen:
Erläuterung:
In der
onCreateViewHolder
Methode können wir überprüfenviewType
und je nach Wert (unsere "spezielle" Art) ein spezielles Layout aufblasen.Beispielsweise:
wo
class ItemElement
undclass TitleElement
kann wie gewöhnlich aussehenViewHolder
:Die Idee von all dem ist also interessant. Aber ich bin interessiert, ob es effektiv ist, weil wir die Datenliste sortieren müssen. Und ich denke, das wird die Geschwindigkeit verringern. Wenn Sie darüber nachdenken, schreiben Sie mir bitte :)
Und auch die offene Frage: Wie soll das "spezielle" Layout oben gehalten werden, während die Artikel recycelt werden? Vielleicht kombinieren Sie das alles mit
CoordinatorLayout
.quelle