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.