Poner una barra de progreso indeterminada como pie de página en una cuadrícula de RecyclerView
Cómo obtener indicador circular indeterminado para "Desplácese hasta cargar más" en una cuadrícula RecycleView?
El patrón se describe allí: http://www.google.com/design/spec/components/progress-activity.html#progress-activity-behavior en "Cargas en dos fases" y "Ejemplo 2: Desplácese hacia arriba para cargar más "Videos de ejemplo.
- La vista de pie de página para ListView no se muestra en 1 dispositivo, pero está en otro?
- ¿Cómo configurar Header, Scrollable content y Footer? en Android
- Eliminar ListView pie de página Click Listener
- Cómo quitar el divisor inferior del pie de página en una vista de lista de android
- Problema al eliminar el pie de página de ListView con removeFooterView ()
Estoy tratando de lograr esto usando el nuevo RecyclerView, pero no puedo encontrar una forma "no demasiado hackeada" para hacer eso, en primer lugar porque no hay una manera de agregar un pie de página que cubren una fila completa en la cuadrícula . ¿Alguna sugerencia?
- Cómo agregar un pie de página en ListView?
- ¿Cómo implementar el pie de página pegajoso en recyclerview
- Agregar un encabezado / pie de página en un listview en xml
- ¿Cómo puedo crear una barra de botones de encabezado o pie de página para mi aplicación de Android?
- ¿Cómo puedo hacer que el pie de un ListView se estire para llenar el espacio restante?
- Android: Pie de página en un ListView
- Espacio vacío entre el encabezado listview y el primer elemento
- ¿Cómo tener un pie de página fijo con scrollview en android?
Es muy sencillo hacerlo.
La solución es utilizar la misma aproximación de LinearLayoutManager
con un GridLayoutManager
y luego usar el método setSpanSizeLookup
en el LayoutManager
como este:
mLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { switch(myAdapter.getItemViewType(position)){ case MyAdapter.VIEW_TYPES.Product: return 1; case MyAdapter.VIEW_TYPES.Progress: return 2; //number of columns of the grid default: return -1; } } });
Esto automáticamente hará que el elemento cubra una fila completa de la cuadrícula (si la fila no está totalmente vacía, este elemento pasa a la siguiente fila).
Nota solución a continuación tiene algunos problemas potenciales y la limitación, para la solución revisada por favor marque esto Agregar elementos a Endless Scroll RecyclerView con ProgressBar en la parte inferior
Aquí está la solución que surgió recientemente: la idea es tener RecyclerView con 2 tipo de elementos uno es nuestros elementos habituales el segundo es la barra de progreso, entonces tenemos que escuchar evento de desplazamiento y decidir vamos a cargar más y mostrar la barra de progreso o no . Así que desde la idea hasta el código de ejemplo
Progress_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ProgressBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/progressBar" android:indeterminate="true" style="@android:style/Widget.Holo.ProgressBar" android:layout_gravity="center_horizontal"/> </LinearLayout>
Activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:ring="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/my_recycler_view" android:scrollbars="vertical" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout>
EndlessRecyclerOnScrollListener.java
public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener { public static String TAG = EndlessRecyclerOnScrollListener.class.getSimpleName(); private int previousTotal = 0; // The total number of items in the dataset after the last load private boolean loading = true; // True if we are still waiting for the last set of data to load. private int visibleThreshold = 1; // The minimum amount of items to have below your current scroll position before loading more. int firstVisibleItem, visibleItemCount, totalItemCount; private int current_page = 1; private LinearLayoutManager mLinearLayoutManager; public EndlessRecyclerOnScrollListener(LinearLayoutManager linearLayoutManager) { this.mLinearLayoutManager = linearLayoutManager; } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); visibleItemCount = recyclerView.getChildCount(); totalItemCount = mLinearLayoutManager.getItemCount(); firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition(); if (loading) { if (totalItemCount > previousTotal+1) { loading = false; previousTotal = totalItemCount; } } if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) { // End has been reached // Do something current_page++; onLoadMore(current_page); loading = true; } } public abstract void onLoadMore(int current_page); }
MyAdapter.java
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private final int VIEW_ITEM = 1; private final int VIEW_PROG = 0; private List<String> mDataset; public static class TextViewHolder extends RecyclerView.ViewHolder { public TextView mTextView; public TextViewHolder(View v) { super(v); mTextView = (TextView)v.findViewById(android.R.id.text1); } } public static class ProgressViewHolder extends RecyclerView.ViewHolder { public ProgressBar progressBar; public ProgressViewHolder(View v) { super(v); progressBar = (ProgressBar)v.findViewById(R.id.progressBar); } } public MyAdapter(List<String> myDataset) { mDataset = myDataset; } @Override public int getItemViewType(int position) { return mDataset.get(position)!=null? VIEW_ITEM: VIEW_PROG; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RecyclerView.ViewHolder vh; if(viewType==VIEW_ITEM) { View v = LayoutInflater.from(parent.getContext()) .inflate(android.R.layout.simple_list_item_1, parent, false); vh = new TextViewHolder(v); }else { View v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.progress_item, parent, false); vh = new ProgressViewHolder(v); } return vh; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if(holder instanceof TextViewHolder){ ((TextViewHolder)holder).mTextView.setText(mDataset.get(position)); }else{ ((ProgressViewHolder)holder).progressBar.setIndeterminate(true); } } @Override public int getItemCount() { return mDataset.size(); } }
Y finalmente MainActivity.java
package virtoos.com.testapps; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import java.util.ArrayList; import java.util.List; public class MainActivity extends Activity { private RecyclerView mRecyclerView; private LinearLayoutManager mLayoutManager; private MyAdapter mAdapter; private final List<String> myDataset = new ArrayList<>(); private Handler handler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); handler = new Handler(); addItems(20); mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); // use this setting to improve performance if you know that changes // in content do not change the layout size of the RecyclerView mRecyclerView.setHasFixedSize(true); mLayoutManager = new LinearLayoutManager(this); mRecyclerView.setLayoutManager(mLayoutManager); mAdapter = new MyAdapter(myDataset); mRecyclerView.setAdapter(mAdapter); //mRecyclerView.setItemAnimator(new DefaultItemAnimator()); mRecyclerView.setOnScrollListener(new EndlessRecyclerOnScrollListener(mLayoutManager) { @Override public void onLoadMore(int current_page) { //add progress item myDataset.add(null); mAdapter.notifyItemInserted(myDataset.size()); handler.postDelayed(new Runnable() { @Override public void run() { //remove progress item myDataset.remove(myDataset.size() - 1); mAdapter.notifyItemRemoved(myDataset.size()); //add items one by one for (int i = 0; i < 15; i++) { myDataset.add("Item"+(myDataset.size()+1)); mAdapter.notifyItemInserted(myDataset.size()); } //or you can add all at once but do not forget to call mAdapter.notifyDataSetChanged(); } }, 2000); System.out.println("load"); } }); } }
Aquí está una pequeña modificación a la respuesta @Vilen Melkumyan en el RecyclerView.Adapter
que funcionó mejor para mí. Y puede utilizar su EndlessRecyclerOnScrollListener
de la forma que quiera para cargar los datos, también habilitando o deshabilitando el pie de página en cualquier momento.
PS: Trabajó con GridLayoutManager
.
public class MyRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private final int VIEW_TYPE_ITEM = 1; private final int VIEW_TYPE_PROGRESSBAR = 0; private boolean isFooterEnabled = true; private List<String> items; public static class TextViewHolder extends RecyclerView.ViewHolder { public TextView mTextView; public TextViewHolder(View v) { super(v); mTextView = (TextView)v.findViewById(android.R.id.text1); } } public static class ProgressViewHolder extends RecyclerView.ViewHolder { public ProgressBar progressBar; public ProgressViewHolder(View v) { super(v); progressBar = (ProgressBar)v.findViewById(R.id.progressBar); } } public MyRecyclerViewAdapter(List<String> myDataset) { items = myDataset; } @Override public int getItemCount() { return (isFooterEnabled) ? items.size() + 1 : items.size(); } @Override public int getItemViewType(int position) { return (isFooterEnabled && position >= items.size() ) ? VIEW_TYPE_PROGRESSBAR : VIEW_TYPE_ITEM; } /** * Enable or disable footer (Default is true) * * @param isEnabled boolean to turn on or off footer. */ public void enableFooter(boolean isEnabled){ this.isFooterEnabled = isEnabled; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RecyclerView.ViewHolder vh; if(viewType== VIEW_TYPE_ITEM) { View v = LayoutInflater.from(parent.getContext()) .inflate(android.R.layout.simple_list_item_1, parent, false); vh = new TextViewHolder(v); }else { View v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.progressbar, parent, false); vh = new ProgressViewHolder(v); } return vh; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if(holder instanceof ProgressViewHolder){ ((ProgressViewHolder)holder).progressBar.setIndeterminate(true); } else if(items.size() > 0 && position < items.size()) { ((TextViewHolder)holder).mTextView.setText(items.get(position)); } } }
Mis 2 centavos, la paz !!
Echa un vistazo a mi solución en https://github.com/ramirodo/endless-recycler-view-adapter o https://bintray.com/ramiro/android/endless-recycler-view-adapter . Hay un ejemplo allí y también los pasos para configurar la biblioteca en su proyecto.
Sólo necesita ampliar su adaptador de vista de reciclador mediante la implementación de los métodos necesarios. También puede configurar el diseño del pie de página de progreso.