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?
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.
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.
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.
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
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).
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"));
}
}
});
}
}