Android: Implementing progressbar and "loading..." for Endless List like Android Market
Taking inspiration from Android Market, i have implemented a Endless List which loads more data from the server when we reach the end of the List.
Now, i need to implement the progressbar & "Loading.." text as shown
Sample code to take inspiration from would be great.
Solution 1:
Here is a solution that also makes it easy to show a loading view in the end of the ListView while it's loading.
You can see the classes here:
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/helper/ListViewWithLoadingIndicatorHelper.java - Helper to make it possible to use the features without extending from SimpleListViewWithLoadingIndicator.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/listener/EndlessScrollListener.java - Listener that starts loading data when the user is about to reach the bottom of the ListView.
https://github.com/CyberEagle/OpenProjects/blob/master/android-projects/widgets/src/main/java/br/com/cybereagle/androidwidgets/view/SimpleListViewWithLoadingIndicator.java - The EndlessListView. You can use this class directly or extend from it.
Solution 2:
Add an onScrollListener to the ListView. When the user scrolls, check if the ListView is nearing its end. If yes, then fetch more data. As an example :
public abstract class LazyLoader implements AbsListView.OnScrollListener {
private static final int DEFAULT_THRESHOLD = 10 ;
private boolean loading = true ;
private int previousTotal = 0 ;
private int threshold = DEFAULT_THRESHOLD ;
public LazyLoader() {}
public LazyLoader(int threshold) {
this.threshold = threshold;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(loading) {
if(totalItemCount > previousTotal) {
// the loading has finished
loading = false ;
previousTotal = totalItemCount ;
}
}
// check if the List needs more data
if(!loading && ((firstVisibleItem + visibleItemCount ) >= (totalItemCount - threshold))) {
loading = true ;
// List needs more data. Go fetch !!
loadMore(view, firstVisibleItem,
visibleItemCount, totalItemCount);
}
}
// Called when the user is nearing the end of the ListView
// and the ListView is ready to add more items.
public abstract void loadMore(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount);
}
Activity :
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
ListView listView = (ListView) findViewById(R.id.listView);
listView.setOnScrollListener(new LazyLoader() {
@Override
public void loadMore(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// Fetch your data here !!!
}
});
}
}
You can find the complete implementation at this link
Solution 3:
The other answers here refer to outdated, unmaintained solutions. This article, however, seems to be kept up-to-date: https://github.com/codepath/android_guides/wiki/Endless-Scrolling-with-AdapterViews-and-RecyclerView
There's too much there to put it all in a SO answer, but here's some important bits as of the time I'm writing this answer:
Implementing endless pagination for
RecyclerView
requires the following steps:
- Copy over the EndlessRecyclerViewScrollListener.java into your application.
- Call
addOnScrollListener(...)
on aRecyclerView
to enable endless pagination. Pass in an instance ofEndlessRecyclerViewScrollListener
and implement theonLoadMore
which fires whenever a new page needs to be loaded to fill up the list.- Inside the aforementioned
onLoadMore
method, load additional items into the adapter either by sending out a network request or by loading from another source.To start handling the scroll events for steps 2 and 3, we need to use the
addOnScrollListener()
method in ourActivity
orFragment
and pass in the instance of theEndlessRecyclerViewScrollListener
with the layout manager as shown below:public class MainActivity extends Activity { // Store a member variable for the listener private EndlessRecyclerViewScrollListener scrollListener; @Override protected void onCreate(Bundle savedInstanceState) { // Configure the RecyclerView RecyclerView rvItems = (RecyclerView) findViewById(R.id.rvContacts); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); rvItems.setLayoutManager(linearLayoutManager); // Retain an instance so that you can call `resetState()` for fresh searches scrollListener = new EndlessRecyclerViewScrollListener(linearLayoutManager) { @Override public void onLoadMore(int page, int totalItemsCount, RecyclerView view) { // Triggered only when new data needs to be appended to the list // Add whatever code is needed to append new items to the bottom of the list loadNextDataFromApi(page); } }; // Adds the scroll listener to RecyclerView rvItems.addOnScrollListener(scrollListener); } // Append the next page of data into the adapter // This method probably sends out a network request and appends new data items to your adapter. public void loadNextDataFromApi(int offset) { // Send an API request to retrieve appropriate paginated data // --> Send the request including an offset value (i.e `page`) as a query parameter. // --> Deserialize and construct new model objects from the API response // --> Append the new data objects to the existing set of items inside the array of items // --> Notify the adapter of the new items made with `notifyItemRangeInserted()` } }