wake-up-neo.com

Erhalten Sie sichtbare Elemente in RecyclerView

Ich muss wissen, welche Elemente aktuell in meinem RecyclerView angezeigt werden. Es gibt keine Entsprechung zur OnScrollListener.onScroll(...) -Methode für ListViews. Ich habe versucht mit View.getGlobalVisibleRect(...) zu arbeiten, aber dieser Hack ist zu hässlich und funktioniert nicht immer auch.

Jemand irgendwelche Ideen?

221
rekire

Das erste/letzte sichtbare untergeordnete Element hängt von LayoutManager..__ ab. Wenn Sie LinearLayoutManager oder GridLayoutManager verwenden, können Sie verwenden 

int findFirstVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();

Zum Beispiel:

GridLayoutManager layoutManager = ((GridLayoutManager)mRecyclerView.getLayoutManager());
int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();

Für LinearLayoutManager hängt first/last von der Reihenfolge des Adapters ab. Keine Kinder von RecyclerView abfragen; LayoutManager kann es vorziehen, mehr Elemente anzuordnen, als für die Zwischenspeicherung sichtbar sind.

500
yigit

Schließlich habe ich eine Lösung gefunden, um zu wissen, ob das aktuelle Element sichtbar ist, und zwar anhand des onBindViewHolder-Ereignisses im Adapter.

Der Schlüssel ist die Methode isViewPartiallyVisible von LayoutManager.

In Ihrem Adapter können Sie den LayoutManager aus der RecyclerView erhalten, die Sie als Parameter aus dem Ereignis onAttachedToRecyclerView erhalten.

7
Ernesto Vega

Sie können recyclerView.getChildAt() verwenden, um jedes sichtbare untergeordnete Element abzurufen. Wenn Sie im Adaptercode ein Tag convertview.setTag(index) in dieser Ansicht setzen, können Sie es mit den Adapterdaten verknüpfen.

4

Für StaggeredGridLayoutManager machen Sie folgendes:

RecyclerView rv = findViewById(...);
StaggeredGridLayoutManager lm = new StaggeredGridLayoutManager(...);
rv.setLayoutManager(lm);

Und um sichtbare Elementansichten zu erhalten:

int[] viewsIds = lm.findFirstCompletelyVisibleItemPositions(null);
ViewHolder firstViewHolder = rvPlantios.findViewHolderForLayoutPosition(viewsIds[0]);
View itemView = viewHolder.itemView;

Denken Sie daran, zu überprüfen, ob es leer ist.

Die folgenden Linear / Grid LayoutManager-Methoden können verwendet werden, um zu prüfen, welche Elemente visible sind.

int findFirstVisibleItemPosition();
int findLastVisibleItemPosition();
int findFirstCompletelyVisibleItemPosition();
int findLastCompletelyVisibleItemPosition();

und wenn Sie is item visible on screen für einen bestimmten Schwellenwert verfolgen möchten, können Sie auf den folgenden Blog verweisen.

https://proandroiddev.com/detecting-list-items-perceived-by-user-8f164dfb1d05

0
Sumit Jain

Nachtrag :

Die vorgeschlagenen Funktionen findLast ... Position () do not funktionieren in einem Szenario mit einer reduzierten Symbolleiste ordnungsgemäß, während die Symbolleiste erweitert ist.

Die Ansicht des Recyclers scheint eine feste Höhe zu haben, und während die Symbolleiste erweitert wird, wird der Recycler nach unten bewegt, teilweise aus dem Bildschirm heraus. Infolgedessen sind die Ergebnisse der vorgeschlagenen Funktionen zu hoch. Beispiel: Als letztes sichtbares Element wird # 9 angegeben, aber tatsächlich ist Element # 7 das letzte, das auf dem Bildschirm angezeigt wird.

Dieses Verhalten ist auch der Grund, warum meine Ansicht oft nicht an die richtige Position gescrollt hat, d. H. ScrollToPosition () funktionierte nicht richtig (ich habe die Symbolleiste schließlich programmgesteuert reduziert).

0

für diejenigen, die eine Logik haben, die innerhalb des RecyclerView-Adapters implementiert werden soll, können Sie weiterhin den @ernesto-Ansatz in Kombination mit einem on scrollListener verwenden, um what you want abzurufen, wenn der RecyclerView aufgerufen wird. Im Inneren des Adapters haben Sie ungefähr Folgendes:

@Override
    public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if(manager instanceof LinearLayoutManager && getItemCount() > 0) {
            LinearLayoutManager llm = (LinearLayoutManager) manager;
            recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                }

                @Override
                public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                        int visiblePosition = llm.findFirstCompletelyVisibleItemPosition();
                        if(visiblePosition > -1) {
                            View v = llm.findViewByPosition(visiblePosition);
                            //do something
                            v.setBackgroundColor(Color.parseColor("#777777"));
                        }
                }
            });
        }
    }
0
Aleyam