2016-01-26 16 views
13

Ho un RecyclerView, ho aggiunto l'elenco di dati in RecyclerView. Voglio aggiungere nuovi dati, quando l'ultimo elemento RecyclerView diventa visibile sullo schermo. Successivamente, desidero effettuare una chiamata al servizio Web e aggiornare i dati di RecyclerView. Come posso raggiungere questo obiettivo?Come posso identificare che l'ultimo elemento di RecyclerView è visibile sullo schermo?

Qualche suggerimento?

+1

use 'android.support.v7.widget.RecyclerView.OnScrollListener' – pskink

+0

Conosco il listener di scroll ma il mio problema si verifica quando l'utente elimina tra gli elementi quindi come faccio a sapere se il mio ultimo elemento della lista è diventato visibile così posso aggiornare l'elenco o effettuare una chiamata al servizio web? –

+0

quindi utilizzare 'onBindViewHolder', quindi – pskink

risposta

1

Questo ha funzionato per me, ho usato usato ascoltatore recycleview di scorrimento per raggiungere questo obiettivo:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { 
      @Override 
      public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 
       LinearLayoutManager layoutManager=LinearLayoutManager.class.cast(recyclerView.getLayoutManager()); 
       int totalItemCount = layoutManager.getItemCount(); 
       int lastVisible = layoutManager.findLastVisibleItemPosition(); 

       boolean endHasBeenReached = lastVisible + 5 >= totalItemCount; 
       if (totalItemCount > 0 && endHasBeenReached) { 
        //you have reached to the bottom of your recycler view 
       } 
      } 
     }); 

Grazie.

+0

sì, questa sembra essere la risposta accettata .. semplice e meno workaround necessario +1 per quello –

15

Ci sono diversi modi per ottenere questo risultato, ma un modo sarebbe quello di utilizzare onBindViewHolder il metodo di scheda:

@Override 
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
     if (position == mData.length - 1) { 
      // load more data here. 
     } 

     /// binding logic 
    } 

Quando il metodo bind viene chiamato con l'ultima posizione della vostra fonte di dati, questo è un buon indica che l'ultima cella sta per essere visualizzata e un buon momento per attivare una chiamata di ricarica. Potrebbe essere necessario aggiungere ulteriori salvaguardie alla condizione per assicurarsi che non stia già caricando più dati, ma questo dovrebbe aiutarti a iniziare.

Un'altra opzione comporterebbe la modifica del LayoutManager. L'idea qui è di trovare la posizione dell'ultimo oggetto visibile. Se quella posizione è uguale all'ultima voce del set di dati, devi attivare una ricarica. Questa chiamata dovrebbe essere fatto nei tuoi LayourManager'sonLayoutChildren & scrollVerticallyBy (a patto di utilizzare scorrimento verticale) metodi:

@Override 
    public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) { 

     final int result = super.scrollVerticallyBy(dy, recycler, state); 

     if (findLastVisibleItemPosition() == mData.length - 1) { 
      loadMoreData(); 
     } 

     return result; 

    } 

    @Override 
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { 
     super.onLayoutChildren(recycler, state); 

     if (findLastVisibleItemPosition() == mData.length - 1) { 
      loadMoreData(); 
     } 
    } 

stessa di prima, è necessario assicurarsi di non innescare un carico di dati più di una volta, poiché è possibile questa condizione si verificherà più di una volta.

Spero che questo aiuti!

+0

Ricordo che recyclerview avrà un paio di altri viewholder vincolati che saranno fuori dallo schermo. Quindi, penso che il controllo dell'ultimo elemento potrebbe non aiutare lo – cgr

+0

a collegarlo quando la vista sta per diventare visibile, quindi credo che dovrebbe essere abbastanza buono per te. Aggiungerò un'altra opzione allo –

+0

Sì, si legherà quando diventerà visibile. Quindi, l'ultimo che ha vincolato non deve essere stato già visibile.Quindi, abbiamo ancora bisogno di condizioni per controllare la visibilità. Può anche provare findLastVisibleItemPosition() in LinearLayoutManager. – cgr

3

Se qualcuno incappare in questo messaggio this is un tutorial semplice e veloce su come farlo:

Tutto quello che dovete fare è:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { 
    @Override 
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 
     super.onScrollStateChanged(recyclerView, newState); 
    } 

    @Override 
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 
     super.onScrolled(recyclerView, dx, dy); 
     int visibleItemCount  = lm.getChildCount(); 
     int totalItemCount   = lm.getItemCount(); 
     int firstVisibleItemPosition= lm.findFirstVisibleItemPosition(); 

     // Load more if we have reach the end to the recyclerView 
     if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0) { 
      loadMoreItems(); 
     } 
    } 
}); 

Allora la vostra loadMoreItems() dovrebbe apparire in questo modo:

private void loadMoreItems() { 
    // init offset=0 the frist time and increase the offset + the PAGE_SIZE when loading more items 
    queryOffset = queryOffset + PAGE_SIZE; 
    // HERE YOU LOAD the next batch of items 
    List<Items> newItems = loadItems(queryOffset, PAGE_SIZE); 

    if (newItems.size() > 0) { 
     items.addAll(newItems); 
     adapter.notifyDataSetChanged(); 
    } 
} 
0
@Override 
public void onBindViewHolder(final RecyclerView.ViewHolderholder, int position) { 

    if (!list.isEmpty() || list== null) { 

     if (position == (list.size() - 1)) { 

      // add new data (add data to list) 
      this.notifyDataSetChanged(); 

     } 

    } 


} 
Problemi correlati