recyclerview - Lista sin fin de Android
llenar un listview android (9)
Aquí hay una solución que también facilita la visualización de una vista de carga al final de ListView mientras se está cargando.
Puedes ver las clases aquí:
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java - Ayuda para hacer que sea posible utilizar el características sin extenderse desde SimpleListViewWithLoadingIndicator.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java - Listener que comienza a cargar datos cuando el usuario Está a punto de llegar al fondo del ListView.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java - The EndlessListView. Puedes usar esta clase directamente o extenderla.
¿Cómo puedo crear una lista en la que cuando llegue al final de la lista me notifiquen para poder cargar más elementos?
En Ognyan Bankov GitHub
encontré una solución simple y funcional.
Hace uso de la Volley HTTP library
que hace que las redes para aplicaciones de Android sean más fáciles y, lo que es más importante, más rápidas. Volley está disponible a través del repositorio abierto de AOSP.
El código dado demuestra:
- ListView que se llena con las solicitudes HTTP paginadas.
- Uso de NetworkImageView.
- Paginación "sin fin" de ListView con lectura anticipada.
Para la consistencia futura bifurcé repo de Bankov .
He estado trabajando en otra solución muy similar a esa, pero estoy usando un footerView
para dar la posibilidad al usuario de descargar más elementos haciendo clic en el footerView
, estoy usando un "menú" que se muestra arriba del ListView
y en el En la parte inferior de la vista principal, este "menú" oculta la parte inferior de ListView
, por lo que, cuando el listView
se desplaza, el menú desaparece y cuando el estado de desplazamiento está inactivo, el menú vuelve a aparecer, pero cuando el usuario se desplaza hasta el final de listView
, "Pregunto" para saber si se muestra footerView
en ese caso, el menú no aparece y el usuario puede ver footerView
para cargar más contenido. Aquí el código:
Saludos.
listView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// TODO Auto-generated method stub
if(scrollState == SCROLL_STATE_IDLE) {
if(footerView.isShown()) {
bottomView.setVisibility(LinearLayout.INVISIBLE);
} else {
bottomView.setVisibility(LinearLayout.VISIBLE);
} else {
bottomView.setVisibility(LinearLayout.INVISIBLE);
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
}
});
La clave de este problema es detectar el evento de carga de más, iniciar una solicitud asíncrona de datos y luego actualizar la lista. También se necesita un adaptador con indicador de carga y otros decoradores. De hecho, el problema es muy complicado en algunos casos de esquina. Solo una implementación OnScrollListener
no es suficiente, porque a veces los elementos no llenan la pantalla.
He escrito un paquete personal que admite una lista interminable para RecyclerView
, y también proporciono una implementación de cargador asíncrono AutoPagerFragment
que hace que sea muy fácil obtener datos de una fuente de varias páginas. Puede cargar cualquier página que desee en un RecyclerView
en un evento personalizado, no solo en la página siguiente.
Aquí está la dirección: https://github.com/SphiaTower/AutoPagerRecyclerManager
La mejor solución hasta ahora que he visto está en la biblioteca FastAdapter para vistas de recicladores. Tiene un EndlessRecyclerOnScrollListener
.
Aquí hay un ejemplo de uso: EndlessRecyclerOnScrollListener
Una vez que lo usé para la lista de desplazamiento sin fin, me di cuenta de que la configuración es muy robusta. Definitivamente lo recomendaría.
Puede detectar el final de la lista con la ayuda de OnScrollListener , el código de trabajo se presenta a continuación:
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (view.getAdapter() != null && ((firstVisibleItem + visibleItemCount) >= totalItemCount) && totalItemCount != mPrevTotalItemCount) {
Log.v(TAG, "onListEnd, extending list");
mPrevTotalItemCount = totalItemCount;
mAdapter.addMoreData();
}
}
Otra forma de hacerlo (dentro del adaptador) es la siguiente:
public View getView(int pos, View v, ViewGroup p) {
if(pos==getCount()-1){
addMoreData(); //should be asynctask or thread
}
return view;
}
Tenga en cuenta que este método se llamará muchas veces, por lo que debe agregar otra condición para bloquear varias llamadas de addMoreData()
.
Cuando agregue todos los elementos a la lista, llame a notifyDataSetChanged() dentro de su adaptador para actualizar la Vista (debe ejecutarse en el hilo de la IU - runOnUiThread )
Puede que sea un poco tarde, pero la siguiente solución fue muy útil en mi caso. De una manera, todo lo que necesita hacer es agregar a su ListView un Footer
y crear para él addOnLayoutChangeListener
.
http://developer.android.com/reference/android/widget/ListView.html#addFooterView(android.view.View)
Por ejemplo:
ListView listView1 = (ListView) v.findViewById(R.id.dialogsList); // Your listView
View loadMoreView = getActivity().getLayoutInflater().inflate(R.layout.list_load_more, null); // Getting your layout of FooterView, which will always be at the bottom of your listview. E.g. you may place on it the ProgressBar or leave it empty-layout.
listView1.addFooterView(loadMoreView); // Adding your View to your listview
...
loadMoreView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
Log.d("Hey!", "Your list has reached bottom");
}
});
Este evento se dispara una vez cuando un pie de página se hace visible y funciona como un amuleto.
Solo quería aportar una solución que utilicé para mi aplicación.
También se basa en la interfaz OnScrollListener
, pero descubrí que tiene un rendimiento de desplazamiento mucho mejor en los dispositivos de gama baja, ya que ninguno de los cálculos de recuento total / visible se realiza durante las operaciones de desplazamiento.
- Deje que su
ListFragment
oListActivity
implementenOnScrollListener
Agregue los siguientes métodos a esa clase:
@Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { //leave this empty } @Override public void onScrollStateChanged(AbsListView listView, int scrollState) { if (scrollState == SCROLL_STATE_IDLE) { if (listView.getLastVisiblePosition() >= listView.getCount() - 1 - threshold) { currentPage++; //load more list items: loadElements(currentPage); } } }
donde
currentPage
es la página de sucurrentPage
de datos que debe agregarse a su lista, ythreshold
es el número de elementos de la lista (contados desde el final) que deberían, si están visibles, desencadenar el proceso de carga. Si establece elthreshold
en0
, por ejemplo, el usuario tiene que desplazarse hasta el final de la lista para cargar más elementos.(Opcional) Como puede ver, la "comprobación de carga más" solo se llama cuando el usuario deja de desplazarse. Para mejorar la facilidad de uso, puede inflar y agregar un indicador de carga al final de la lista a través de
listView.addFooterView(yourFooterView)
. Un ejemplo para tal vista de pie de página:<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/footer_layout" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10dp" > <ProgressBar android:id="@+id/progressBar1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_gravity="center_vertical" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toRightOf="@+id/progressBar1" android:padding="5dp" android:text="@string/loading_text" /> </RelativeLayout>
(opcional) Finalmente, elimine ese indicador de carga llamando a
listView.removeFooterView(yourFooterView)
si no hay más elementos o páginas.
Una solución es implementar un OnScrollListener
y realizar cambios (como agregar elementos, etc.) al ListAdapter
en un estado conveniente en su método onScroll
.
La siguiente ListActivity
muestra una lista de enteros, comenzando con 40, agregando elementos cuando el usuario se desplaza al final de la lista.
public class Test extends ListActivity implements OnScrollListener {
Aleph0 adapter = new Aleph0();
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setListAdapter(adapter);
getListView().setOnScrollListener(this);
}
public void onScroll(AbsListView view,
int firstVisible, int visibleCount, int totalCount) {
boolean loadMore = /* maybe add a padding */
firstVisible + visibleCount >= totalCount;
if(loadMore) {
adapter.count += visibleCount; // or any other amount
adapter.notifyDataSetChanged();
}
}
public void onScrollStateChanged(AbsListView v, int s) { }
class Aleph0 extends BaseAdapter {
int count = 40; /* starting amount */
public int getCount() { return count; }
public Object getItem(int pos) { return pos; }
public long getItemId(int pos) { return pos; }
public View getView(int pos, View v, ViewGroup p) {
TextView view = new TextView(Test.this);
view.setText("entry " + pos);
return view;
}
}
}
Obviamente, debería usar hilos separados para acciones de ejecución prolongada (como cargar datos web) y es posible que desee indicar el progreso en el último elemento de la lista (como lo hacen las aplicaciones market o gmail).