2017-01-11 4 views
5

Einwickeln Was ichHorizontal RecyclerView mit variabler Artikel Höhen nicht richtig

enter image description here

Der Artikel Blick über die gesamte Höhe des Elements besetzen sollte

enter image description here

Es könnte zu erreichen beabsichtigen Sei es, dass die Artikelhöhe kleiner ist als die Höhe des höchsten Artikels in der Recycleransicht, in diesem Fall sollte es einfach oben bleiben im Screenshot oben.

Der Fehler ich in laufen

enter image description here

Wie in der Abbildung oben sind Ansichten, abgeschnitten zu werden.

Was ich versucht habe bisher

Zunächst ging ich mit wrap_content auf dem recyclerview, jetzt, dass es unterstützt wird. Es funktionierte nicht, wenn keine der auf dem Bildschirm zu dieser Zeit sichtbaren Ansichten die höchsten war. Dies macht Sinn für die Anordnung der Ansichtshierarchie. Wie kann die Höhe von etwas, das noch nicht an irgendwelche Daten gebunden ist, berechnet werden, wenn die Höhe von diesen Daten abhängt?

Behelfslösung Zeit: S

Statt ein benutzerdefinierten Layoutmanager versucht, ging ich zuerst mit dem, was ich fühlte mich getan werden müssen - alle Artikelansichten zu Beginn Auslegen ihre Höhe, um herauszufinden.

Es gibt eine Fortschrittsleiste und eine Animation, die im oberen Teil des Bildschirms angezeigt wird, um die Aufmerksamkeit des Benutzers zu erregen, während all dies geschieht und die Sichtbarkeit von recycleview auf unsichtbar gesetzt ist. Ich benutze zwei Dinge, eines hat nicht genügt - ich habe einen Beobachter in den Adapter onViewAttached() Anruf angeschlossen und ich habe auch einen Scroll-Change-Listener verwendet. Es gibt einen LinearSnapHelper, der an die Recycler-Ansicht angehängt ist, um an der nächsten (nächsten oder vorherigen, je nach Scroll-Richtung) Position beim Scrollen zu fangen.

In diesem Setup

  1. Ich bin in der recyclerview jeder Position gehen layoutManager.smoothScrollToPosition()
  2. Erste das Kind Blick Höhe

     View currentChildView = binding.nextRv.getChildAt(layoutManager.findFirstCompletelyVisibleItemPosition()); 
         if (currentChildView != null) { 
          currentChildHeight = currentChildView.getHeight(); 
         } 
    

in scroll ändern Listener mit auf RecyclerView.SCROLL_STATE_IDLE oder indem Sie die Höhe zu dem oben genannten Observer beigefügt im Adapter onVie wAttachedToWindow()

@Override 
public void onViewAttachedToWindow(BindingViewHolder holder) { 
    if (mObserver != null) { 
     mObserver.onViewAttached(holder.binding.getRoot().getHeight()); 
    } 
} 
  1. ein maxHeight Speicher, die das Maximum von maxHeight und neuer Kindergröße ändert.

Wie offensichtlich ist, ist dies hässlich. Außerdem gibt es mir nicht die aktuelle Ansichtshöhe - onAttached bedeutet, dass es nur gerade angebracht, nicht gemessen und ausgelegt ist. Es ist die wiederverwendbare Ansicht, nicht die Ansicht, die an das aktuelle Datenelement gebunden ist. Das stellt Probleme wie das oben abgebildete Abschneiden der Ansicht dar.


Ich habe auch wrap_content Höhe auf der Recycler Ansicht versucht und bis zum Recycler von Recycler der Eltern ungültig zu machen und das Kind auf Blättern zu SCROLL_STATE_IDLE kommen. Funktioniert nicht.


Ich bin mir nicht sicher, wie ein benutzerdefinierter Layoutmanager hier helfen kann.

Kann mir jemand die richtige Richtung zeigen?

+0

können Sie Ihre XML-Datei – Redman

+0

finden Sie es [hier] (https://gist.github.com/adroitandroid/85e7a66d7f796379649c2d9eab26cf76) –

+0

Die recyclerview in Frage ist die, mit der ID "next_rv" hinzufügen.Eigentlich für die oben beschriebene Lösung, zunächst habe ich es auf Höhe match_parent gesetzt und später die Höhe auf die 'maxHeight' zurückgesetzt –

Antwort

1

In Ihrem Adapter, wo ich zwei Karten über und ein anderer auf der Unterseite

finden, wie ich definiert haben würde mein Layout ist wie folgt:

Cardview1 

    LinearLayout1 --> orientation vertical 

    cardview2 (Top card where text is written) 

    Linearlayout2 (where I can see icons such as like etc)-->orientation horizontal 

nun die Höhe des Linearlayout2 beheben, indem es um Inhalte zu wickeln.

und die Höhe der cardview2 sollte 0DP und fügt Gewicht = 1

Jetzt innen cardview2 ein TextView1 hinzufügen in Höhe und Breite matchparent.

besser innerhalb textview1 hinzufügen ellipsize zu beenden und max Linien

hinzufügen Wenn Sie alle Linien zeigen wollen versuchen können autoresizetextview Bibliothek finden hier gegründet werden ->AutoResizeTextView

Hoffe, es hilft.

+0

Vielen Dank für die Beantwortung. Ellipse ist eine Problemumgehung, es löst meine Abfrage nicht. Ich kenne die autoresizetextview :) aber ich suche nicht nach variablen Schriftgrößen auf meiner Liste. –

3

Ich konnte die Antwort von @Pradeep Kumar Kushwaha nicht akzeptieren, denn gegen eine Lösung möchte ich keine anderen Schriftgrößen in der Liste. Konsistenz ist ein Schlüsselelement im Design. Die zweite Alternative, die er gab, konnte nicht funktionieren, weil ich mit Ellipsize einen "mehr" Button irgendeiner Art geben musste, damit der Benutzer den gesamten Inhalt lesen kann und meine Textansicht bereits einen Klick ausführt. Putting mehr irgendein Platz sonst wäre wieder nicht gut Design.

Wenn Sie das Design mit dem einfachen Kompromiss der Größenanpassung der Recycleransicht ändern, wenn das höchste abgeschnittene Objekt in den Fokus kommt, wird es zum einfachen Anwendungsfall von notifyItemChanged(). Selbst für den Versuch, den ich mit dem View-Beobachter und Scroll-State-Listener gemacht habe, könnte notifyItemChanged verwendet werden, aber dieser Ansatz ist einfach zu hacky. Damit kann ich sowohl im Code als auch im Design leben. Hier geht der benötigte Code.

@Override 
public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 
    if (newState == RecyclerView.SCROLL_STATE_IDLE) { 
     int position = ((LinearLayoutManager) binding.nextRv.getLayoutManager()) 
       .findFirstVisibleItemPosition(); 
     if (position != nextSnippetAdapter.getItemCount() - 1) { 
      binding.nextRv.getAdapter().notifyItemRangeChanged(position, 2); 
     } else { 
      binding.nextRv.getAdapter().notifyItemChanged(position); 
     } 
    } 
} 

Für meine spezielle Einrichtung, ruft nur diese beiden Elemente aufrufen. Es kann weiter optimiert werden, um in den meisten Fällen nach einem einzelnen Element bei position + 1 zu rufen, und in Winkelsituationen (wörtlich) das geeignete zu prüfen und aufzurufen.

+0

Es ist ein Design-Kompromiss, da die Dinge auf dem Bildschirm bewegt werden müssen, um das gesamte Element in den Fokus zu bringen (mit 'binding.contentScrollView.fullScroll (ScrollView.FOCUS_DOWN);') –

+0

Eigentlich ist das nicht so ein großer Kompromiss. Wenn ich nicht blättern gehe, um nach unten zu scrollen, sieht alles gut aus. Es ist wahrnehmbar, dass die Ansicht den Bildschirm vergrößert und überfüllt hat, so dass erwartet werden kann, dass ein Benutzer sich selbst scrollt, um die gesamte Sache zu betrachten. –