Ottieni oggetti visibili in RecyclerView


Risposte:


579

Il primo / ultimo figlio visibile dipende da LayoutManager. Se stai usando LinearLayoutManagero GridLayoutManager, puoi usare

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

Per esempio:

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

Per LinearLayoutManager, il primo / l'ultimo dipende dall'ordinamento dell'adattatore. Non interrogare i bambini da RecyclerView; LayoutManagerpotrebbe preferire il layout di più elementi di quelli visibili per la memorizzazione nella cache.


10
Esiste la possibilità di accedere a questi metodi da RecyclerView.Adapter senza passare il riferimento a LayoutManager?
Yorgi,

3
Come @Yorgi - all'interno dell'adattatore sembra utile. Mi chiedo se ci sia qualche modello che puoi sviluppare usando onBindViewHolder per tenere traccia di quelli che sono effettivamente sullo schermo mentre l'utente scorre.
RoundSparrow hilltx

7
getItemCountpuò restituire 1 e findFirstVisibleItemPosition-1 sulla stessa chiamata.
mbmc,

4
cosa puoi suggerire su StaggeredLayoutManager?
Hornet2319

37
Questi metodi sono così inaffidabili da essere completamente inutili. Soprattutto dopo aver informatoDataSetChanged / itemRemoved / RangeChanged
JK

12

Infine, ho trovato una soluzione per sapere se l'elemento corrente è visibile, dall'evento onBindViewHolder nell'adattatore.

La chiave è il metodo isViewPartiallyVisible da LayoutManager.

Nel tuo adattatore, puoi ottenere LayoutManager da RecyclerView, che ottieni come parametro dall'evento onAttachedToRecyclerView .


Ma dove chiameresti questo metodo in cui il gestore del layout non è nullo?
6rchid

È necessario attendere l'evento onAttachedToRecyclerView dell'adattatore. In tal caso si riceve RecyclerView come parametro; e quindi è possibile ottenere LayoutManager da RecyclerVie e salvarlo in una var globale. Se LayoutManager è nullo, probabilmente potrebbe essere perché non è stato assegnato a RecyclerView in Activity / Fragment / Layout; e prova a creare l'adattatore dopo quell'assegnazione.
Ernesto Vega,

Secondo il codice sorgente, isViewPartiallyVisible è gravemente rotto. Se completamenteVisibile è vero, tornerà vero se la vista è completamente visibile. Tuttavia, se falso, annulla solo il risultato che restituisce vero se la vista è parzialmente visibile o non visibile. Anche la documentazione non ha senso.
Molanda,


9

per coloro che hanno una logica da implementare all'interno dell'adattatore RecyclerView è comunque possibile utilizzare l'approccio @ernesto in combinazione con un scrollListener per ottenere what you wantcome viene consultato RecyclerView. All'interno dell'adattatore avrai qualcosa del genere:

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

7

È possibile utilizzare recyclerView.getChildAt()per ottenere ogni figlio visibile e l'impostazione di alcuni tag convertview.setTag(index)su queste viste nel codice dell'adattatore ti aiuterà a metterlo in relazione con i dati dell'adattatore.


Il problema con getChildAt () è che l'ordine degli elementi può essere su 5 elementi: 0, 5, 4, 3, 2, 1 (il conteggio figlio è principalmente> = il conteggio degli oggetti visibili). Quindi ho cercato di ottenere l'ordine dell'elemento tramite getGlobalVisibleRect.
rekire il

Qual è il tuo vero requisito, ottenere un bambino visibile (bambino all'interno del limite dello schermo) nell'ordine reale?
Sreejith B Naick,

Ora voglio sapere quale elemento è al centro, in seguito forse mi interessano anche i limiti.
rekire il

1
Riceverai solo oggetti visibili recyclerView.getChildAt(), ecco come RecyclerViewfunziona generalmente . RecyclerViewproverà a conservare solo alcune visualizzazioni figlio che sono attualmente visibili (ovvero all'interno dei limiti dello schermo, non in Visibilità come ANDATO, INVISIBILE) e proverà a riciclare queste visualizzazioni quando l'utente scorre.
Sreejith B Naick,

6
Visualizza visibleChild = recyclerView.getChildAt (0); int positionOfChild = recyclerView.getChildAdapterPosition (visibleChild);
Kevin Lee,

5

Addendum :

Le funzioni proposte FindLast ... posizione () non non funzionano correttamente in uno scenario con una barra degli strumenti collasso mentre la barra degli strumenti è espanso.

Sembra che la vista del riciclatore abbia un'altezza fissa e mentre la barra degli strumenti viene espansa, il riciclatore viene spostato verso il basso, parzialmente fuori dallo schermo. Di conseguenza, i risultati delle funzioni proposte sono troppo elevati. Esempio: l'ultimo elemento visibile viene indicato come # 9, ma in effetti l'articolo # 7 è l'ultimo visualizzato sullo schermo.

Questo comportamento è anche il motivo per cui la mia vista spesso non è riuscita a scorrere nella posizione corretta, ovvero scrollToPosition () non ha funzionato correttamente (ho infine chiuso la barra degli strumenti a livello di codice).


Questo è vero, ma è così che funziona la barra degli strumenti di compressione. Ho smesso di sviluppare app Android un anno fa, ma posso ricordare questo fatto.
riaccendere

4

I seguenti Linear / Grid LayoutManagermetodi possono essere utilizzati per verificare quali elementi sonovisible

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

e se vuoi tenere traccia is item visible on screendi qualche soglia, puoi fare riferimento al seguente blog.

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


3

Per StaggeredGridLayoutManagerfare questo:

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

E per ottenere visualizzazioni degli oggetti visibili:

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

Ricorda di verificare se è vuoto.


Cosa intendi con "controlla se è vuoto"? Come si fa a controllare?
tmm1

viewsIdsè un array e può essere vuoto.
Douglas Nassif Roma Junior
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.