Endless Recyclerview with Progressbar for Pagination

Endless RecyclerView with ProgressBar for pagination

HERE IS SIMPLER AND CLEANER APPROACH.

Implement Endless Scrolling from this Codepath Guide and then follow the following steps.

1. Add progress bar under the RecyclerView.

    <android.support.v7.widget.RecyclerView
android:id="@+id/rv_movie_grid"
android:layout_width="0dp"
android:layout_height="0dp"
android:paddingBottom="50dp"
android:clipToPadding="false"
android:background="@android:color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

</android.support.v7.widget.RecyclerView>

<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
android:background="@android:color/transparent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />

Here android:paddingBottom="50dp" and android:clipToPadding="false" are very important.

2. Get a reference to the progress bar.

progressBar = findViewById(R.id.progressBar);

3. Define methods to show and hide progress bar.

void showProgressView() {
progressBar.setVisibility(View.VISIBLE);
}

void hideProgressView() {
progressBar.setVisibility(View.INVISIBLE);
}

Endless RecyclerView with Progressbar at bottom

I haven't actually run the code, but at least this lines:

current_page++;
loadMore(current_page);
isLoading = true;

should be:

isLoading = true;
current_page++;
loadMore(current_page);

Certainly this must mess up the progress bar and the items since several loads can be launch concurrently.

Adding items to Endless Scroll RecyclerView with ProgressBar at bottom

The problem is that when you add new item internal EndlessRecyclerOnScrollListener doesn't know about it and counters breaking.
As a matter of fact answer with EndlessRecyclerOnScrollListener has some limitations and possible problems, e.g. if you load 1 item at a time it will not work. So here is an enhanced version.

  1. Get rid of EndlessRecyclerOnScrollListener we don't need it anymore
  2. Change your adapter to this which contains scroll listener

    public class MyAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private final int VIEW_ITEM = 1;
    private final int VIEW_PROG = 0;

    private List<T> mDataset;

    // The minimum amount of items to have below your current scroll position before loading more.
    private int visibleThreshold = 2;
    private int lastVisibleItem, totalItemCount;
    private boolean loading;
    private OnLoadMoreListener onLoadMoreListener;

    public MyAdapter(List<T> myDataSet, RecyclerView recyclerView) {
    mDataset = myDataSet;

    if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {

    final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
    recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);

    totalItemCount = linearLayoutManager.getItemCount();
    lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
    if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
    // End has been reached
    // Do something
    if (onLoadMoreListener != null) {
    onLoadMoreListener.onLoadMore();
    }
    loading = true;
    }
    }
    });
    }
    }

    @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).toString());
    } else {
    ((ProgressViewHolder) holder).progressBar.setIndeterminate(true);
    }
    }

    public void setLoaded() {
    loading = false;
    }

    @Override
    public int getItemCount() {
    return mDataset.size();
    }

    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
    this.onLoadMoreListener = onLoadMoreListener;
    }

    public interface OnLoadMoreListener {
    void onLoadMore();
    }

    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);
    }
    }
    }
  3. Change code in Activity class

    mAdapter = new MyAdapter<String>(myDataset, mRecyclerView);
    mRecyclerView.setAdapter(mAdapter);

    mAdapter.setOnLoadMoreListener(new MyAdapter.OnLoadMoreListener() {
    @Override
    public void onLoadMore() {
    //add progress item
    myDataset.add(null);
    mAdapter.notifyItemInserted(myDataset.size() - 1);

    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());
    }
    mAdapter.setLoaded();
    //or you can add all at once but do not forget to call mAdapter.notifyDataSetChanged();
    }
    }, 2000);
    System.out.println("load");
    }
    });

The rest remains unchanged, let me know if this works for you.

How to implement endless scroll (pagination) in recyclerview with StaggeredGridLayoutManager

For your first problem you already have a solution.

StaggeredGridLayoutManager staggeredGridLayoutManager = new 
StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
postRecyclerView.setLayoutManager(
staggeredGridLayoutManager // I have 3 rows
);

For second problem:

postRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener({
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

visibleItemCount = staggeredGridLayoutManager .getChildCount();
totalItemCount = staggeredGridLayoutManager .getItemCount();
int[] firstVisibleItems = null;
firstVisibleItems = mLayoutManager.findFirstVisibleItemPositions(firstVisibleItems);
if(firstVisibleItems != null && firstVisibleItems.length > 0) {
pastVisibleItems = firstVisibleItems[0];
}

if (loading) {
if ((visibleItemCount + pastVisibleItems) >= totalItemCount) {
loading = false;
getData()
}
}
}
});
..........
..........
private void getData() {
mStorage = FirebaseStorage.getInstance();
databaseEventListener = databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
progressBar.setVisibility(View.GONE);
postRecyclerView.setVisibility(View.VISIBLE);
mUploads.clear();
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
Upload upload = dataSnapshot.getValue(Upload.class);
Objects.requireNonNull(upload).setmKey(dataSnapshot.getKey());
mUploads.add(upload);
}
}
//notify the adapter
postsAdapter.notifyDataSetChanged();
loading = true;
}

@Override
public void onCancelled(@NonNull DatabaseError error) {
loading = true;
}
});
}

You might have to call the getData() initially in your onCreate() so that some data loads up on the screen and you have a scroll behavior.

Update:
The second parameter in a StaggeredGridLayoutManager is orientation so instead of context you have to pass orientation StaggeredGridLayoutManager.VERTICAL.

Endless RecyclerView with ProgressBar in Search activity

Add EndlessScrollListener to recyclerView from link:

https://gist.github.com/zfdang/38ae655a4fc401c99789#file-endlessrecycleronscrolllistener-java

override onLoadMore method and call your AsyncFetch Task.

Why i'm getting empty view below progress bar in Recyclerview pagination?

You have this because you didnt set wrap_content in your Progress item's Xml. If you check it and post your Xml i can take a look at.

How to implement endless list with RecyclerView?

Thanks to @Kushal and this is how I implemented it

private boolean loading = true;
int pastVisiblesItems, visibleItemCount, totalItemCount;

mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (dy > 0) { //check for scroll down
visibleItemCount = mLayoutManager.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();

if (loading) {
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading = false;
Log.v("...", "Last Item Wow !");
// Do pagination.. i.e. fetch new data

loading = true;
}
}
}
}
});

Don't forget to add

LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);


Related Topics



Leave a reply



Submit