Placez une barre de progression indéterminée comme pied de page dans une grid RecyclerView

Comment obtenir un indicateur circulaire indéterminé pour “Faire défiler vers le haut pour charger plus” dans une grid RecycleView?

Le modèle est décrit ici: http://www.google.com/design/spec/components/progress-activity.html#progress-activity-behavior dans “Charges à deux phases” et “Exemple 2: faites défiler pour charger plus “exemple de vidéos.

J’essaie d’accomplir ceci en utilisant le nouveau RecyclerView, mais je ne trouve pas de moyen “pas trop piquant” de le faire, tout d’abord parce qu’il n’y a pas moyen d’append un pied de page couvrant une ligne entière de la grid. . Aucune suggestion?

C’est très simple de le faire.

La solution consiste à utiliser la même approche de LinearLayoutManager avec GridLayoutManager , puis à utiliser la méthode setSpanSizeLookup sur le LayoutManager comme ceci:

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

Cela fera automatiquement en sorte que l’élément couvre une ligne complète de la grid (si la ligne n’est pas totalement vide, cet élément passe à la ligne suivante).

Notez que la solution ci-dessous présente certains problèmes et limitations potentiels. Pour la solution révisée, veuillez vérifier celle-ci. Ajout d’éléments à Endless Scroll RecyclerView avec ProgressBar en bas

Voici la solution que j’ai trouvée récemment: l’idée est d’avoir RecyclerView avec 2 types d’éléments dont l’un est notre élément habituel; le second est la barre de progression, alors nous devons écouter scroll et décider si nous allons en charger . Donc de l’idée au code exemple

progress_item.xml

     

activity_main.xml

    

EndlessRecyclerOnScrollListener.java

 public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener { public static Ssortingng 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 { private final int VIEW_ITEM = 1; private final int VIEW_PROG = 0; private List 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 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(); } } 

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

Voici une petite modification de la réponse de @Vilen Melkumyan sur RecyclerView.Adapter qui fonctionnait mieux pour moi. Et vous pouvez utiliser votre EndlessRecyclerOnScrollListener comme vous le souhaitez pour charger les données, et activer ou désactiver le pied de page à tout moment.

PS: Cela a fonctionné avec GridLayoutManager .

 public class MyRecyclerViewAdapter extends RecyclerView.Adapter { private final int VIEW_TYPE_ITEM = 1; private final int VIEW_TYPE_PROGRESSBAR = 0; private boolean isFooterEnabled = true; private List 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 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)); } } } 

Mes 2 centimes, paix !!

Découvrez ma solution sur https://github.com/ramirodo/endless-recycler-view-adapter ou https://bintray.com/ramiro/android/endless-recycler-view-adapter . Il y a un exemple ici et aussi les étapes pour configurer la bibliothèque dans votre projet.

Il vous suffit d’étendre votre adaptateur de vue de recycleur en implémentant les méthodes requirejses. Vous pouvez également configurer la disposition du pied de page de progression.

Vous pouvez simplifier la réponse du Bronx en insérant le code dans un adaptateur.

 public class ArticleGridAdapter extends RecyclerView.Adapter { private final int VIEW_ITEM = 0; private final int VIEW_LOADING = 1; private Context mContext; private List
mArticles = new ArrayList<>(); private RecyclerView mRecyclerView; private GridLayoutManager mManager; public ArticleGridAdapter(Context context, List
articles, RecyclerView recyclerView) { this.mContext = context; this.mArticles = articles; this.mRecyclerView = recyclerView; this.mManager = (GridLayoutManager) recyclerView.getLayoutManager(); mManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { return getItemViewType(position) == VIEW_LOADING ? mManager.getSpanCount() : 1; } }); } }