Comment obtenir un indicateur circulaire indéterminé pour "Faites défiler jusqu'à charger plus" dans une grille RecycleView?
Le modèle est décrit ici: http://www.google.com/design/spec/components/progress-activity.html#progress-activity-behavior dans "Charges en deux phases" et "Exemple 2: Défilement jusqu'à charger plus "exemples de vidéos.
J'essaie d'accomplir cela en utilisant le nouveau RecyclerView, mais je ne trouve pas de moyen "pas trop hack" de le faire, tout d'abord parce qu'il n'y a pas moyen d'ajouter un pied de page couvrant toute une ligne de la grille. . Aucune suggestion?
C'est très simple de faire ça.
La solution consiste à utiliser la même approche de LinearLayoutManager
avec un GridLayoutManager
, puis d'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 va automatiquement faire en sorte que l’objet couvre une ligne complète de la grille (si la ligne n’est pas totalement vide, cet article passe à la ligne suivante).
La solution ci-dessous présente des problèmes et des problèmes potentiels. Veuillez consulter celle-ci pour la solution révisée.Ajout d'éléments à Endless Scroll RecyclerView avec ProgressBar en bas
Voici la solution que j'ai trouvée récemment: progressbar or not . Donc, de l'idée au code de l'exemple
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();
}
}
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<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");
}
});
}
}
Voici une petite modification apportée à la réponse de @Vilen Melkumyan sur le RecyclerView.Adapter
qui fonctionnait mieux pour moi. Et vous pouvez utiliser votre EndlessRecyclerOnScrollListener
comme vous le souhaitez pour le chargement des 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<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));
}
}
}
Mes 2 cents, la paix !!
Découvrez ma solution dans https://github.com/ramirodo/endless-recycler-view-adapter Ou https://bintray.com/ramiro/Android/endless-recycler-view- adaptateur . Il y a un exemple et les étapes pour configurer la bibliothèque dans votre projet.
Vous devez juste étendre votre adaptateur de vue Recycler en implémentant les méthodes requises. Vous pouvez également configurer la mise en page du pied de page de progression.
Vous pouvez simplifier la réponse de Bronx en insérant le code dans un adaptateur.
public class ArticleGridAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int VIEW_ITEM = 0;
private final int VIEW_LOADING = 1;
private Context mContext;
private List<Article> mArticles = new ArrayList<>();
private RecyclerView mRecyclerView;
private GridLayoutManager mManager;
public ArticleGridAdapter(Context context, List<Article> 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;
}
});
}
}