I found this code and adapted it to my project
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = mLayoutManager.getChildCount();
//totalItemCount = mLayoutManager.getItemCount();
int[] firstVisibleItems = null;
firstVisibleItems = mLayoutManager
.findFirstVisibleItemPositions(firstVisibleItems);
if (firstVisibleItems != null && firstVisibleItems.length > 0) {
pastVisibleItems = firstVisibleItems[0];
}
if (!loading && visibleItemCount <= (pastVisibleItems + visibleThreshold)) {
// End has been reached
// Do something
Log.d(TAG, "onLoadMoreListener ");
getTagResults(mQuery, mMinId, mMaxId);
// if (onLoadMoreListener != null) {
// onLoadMoreListener.onLoadMore();
// }
loading = true;
}
}
but this doesnt work it works for linear layout though. I have found lots of code for all the other layouts but i cant find how to load more results when end is reached.
Use following code
RecyclerView.LayoutManager layoutManager;
layoutManager = new GridLayoutManager(getActivity(), 2);
recyclerView.setLayoutManager(layoutManager);
Related
I am using recycler view pagination to show my data. I am loading one page api data by default, for next page i am loading data on the scroll basis of the recycler view. But scroll is not getting called as i can see only 1 page. If i put the condition in on scroll for increasing page no. then on scroll method its not stopping & its calling api till last page in background. Meaning on scroll is calling again and again that I don't want. I want to scroll on basis of current visible items.
live_grid.addOnScrollListener(new PaginationScrollListener(gridLayoutManager) {
#Override
protected void loadMoreItems() {
// TODO: 07/11/16 check if totalPage > 1 before triggering next load
Log.d(TAG, "live_grid loadMoreItems.......");
int visibleItemCount = gridLayoutManager.getChildCount();
int totalItemCount = gridLayoutManager.getItemCount();
int firstVisibleItemPosition = gridLayoutManager.findFirstVisibleItemPosition();
Log.d(TAG, "visibleItemCount: "+ visibleItemCount);
Log.d(TAG, "totalItemCount: "+totalItemCount);
Log.d(TAG, "firstVisibleItemPosition: "+firstVisibleItemPosition);
Log.d(TAG, "currentPage: "+currentPage);
Log.d(TAG, "PAGE_SIZE: "+PAGE_SIZE);
if (!isLoading && !isLastPage) {
// if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0) {
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0 && currentPage < (PAGE_SIZE)) {
//&& totalItemCount >= PAGE_SIZE
firstVisibleItemPosition = visibleItemCount;
loadMoreItems1();
}
}
// presenter.setIsLoading(true);
// presenter.setCurrentPage(presenter.getCurrentPage() + 1);
// presenter.loadNextPlaylist();
}
Try this code..
protected int pastVisibleItems, visibleItemCount, totalItemCount; // define class level..
protected void addScrollListener() {
rvData.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (dy > 0) //check for scroll down
{
visibleItemCount = linearLayoutManager.getChildCount();
totalItemCount = linearLayoutManager.getItemCount();
pastVisibleItems = linearLayoutManager.findFirstVisibleItemPosition();
if ((visibleItemCount + pastVisibleItems) >= totalItemCount) {
pageNumber++; // increase your page
getMessage(); // call api with new Page.
}
}
}
});
}
this method used after recyclerview define and bind adapter.
GridLayoutManger..
RecyclerView.OnScrollListener scrollListener = new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int totalItrem = mLlManager.getItemCount();
int lastViisble = mLlManager.findLastVisibleItemPosition();
Log.d("item", "total item" + totalItrem);
Log.d("visible", "last " + lastViisble);
if (!isLoading && totalItrem == lastViisble + 1 && total_records != mEventList.size()) {
Log.e("msg", "reached end");
//Toast.makeText(mrecyclerview.getContext(), "reached at end", Toast.LENGTH_SHORT).show();
isLoading = true;
mEventList.add(null);
mCurrentPage++;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
getData(mCurrentPage);
}
}, 2000);
}
}
};
I have a RecyclerView,I want it to be SwipeRefreshLayout when pull from top,so I can get the latest 20 item and show it at RecyclerView.At the same time,when reach the 20th item at the bottom,then fetch another 20th item from the database.
Therefore,I get the last item like below,so I can fetch the next 20th item.
//for endless scroll
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = recyclerView.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && (totalItemCount - visibleItemCount)
<= (firstVisibleItem + visibleThreshold)) {
// End has been reached
Log.i("Yaeye!", "end called");
fetchPost(feedItems.get(feedItems.size()-1).getId());
//This function is fetch the next 20th item from database
// Do something
loading = true;
}
}
});
}
This is alright when it reach the bottom of the Recycleview,but the problem is when now is the top(1st item in RecyclerView),I pull down,suppose it fetch the new item,but it crashed.This is the error:
java.lang.ArrayIndexOutOfBoundsException: length=27; index=-1
Here is my code: for the SwipeRefreshLayout to fetch latest 20th item in database
// show loader and fetch messages
swipeRefreshLayout.post(
new Runnable() {
#Override
public void run() {
clear();
fetchIntialPost(); // this one,fetch the latest item
}
}
);
So I know that it cause by,when at the 1st item,it also consider the end of the RecyclerView,so it call fetchPost(feedItems.get(feedItems.size()-1).getId()); this function instead of this function fetchIntialPost();
So now my question is,when at the top(1st item),call fetchIntialPost(); when pull the SwipeRefreshLayout down?and the last item,just call fetchPost(feedItems.get(feedItems.size()-1).getId()); .
Thanks
I solved it by checking the value of feedItems.size()-1 before execute this line of code fetchPost(feedItems.get(feedItems.size()-1).getId());
Here is my working code :
//top and bottom also consider end of the list
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = recyclerView.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
lastVisibleItem = mLayoutManager.findLastVisibleItemPosition();
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && (totalItemCount - visibleItemCount)
<= (firstVisibleItem + visibleThreshold)) {
// End has been reached
//top and bottom also consider end of the list
Log.i("Yaeye!", "end called");
if(feedItems.size() - 1 > 0) {
//when pull down SwipeRefreshLayout,feedItems.size = -1
//so if greater than 0,means is bottom of the list
// Do something
fetchPost(feedItems.get(feedItems.size() - 1).getId());
loading = true;
}else{
//here is the top of the list
}
}
}
});
Can you try this?
lastVisibleItem = mLayoutManager.findLastVisibleItemPosition();
if (!loading && lastVisibleItem == (totalItemCount - 1)) {
// End has been reached
}
I am using a Recyclerview with StaggeredGridLayoutManager with Endless Scroll. I want to do a network call when the last item of the list is visible to the user. So here is my code:
public RecyclerViewAdapter(Context context) {
Log.d(Const.DEBUG, "RecyclerViewAdapter Constructor()");
this.context = context;
final StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = staggeredGridLayoutManager.getItemCount();
lastVisibleItems = staggeredGridLayoutManager.findLastVisibleItemPositions(new int[mStaggeredLayoutManager.getSpanCount()]);
Log.d(Const.DEBUG, "LastVisibleItems: " + Arrays.toString(lastVisibleItems));
Log.d(Const.DEBUG, "LastVisibleItems Count: " + lastVisibleItems.length);
if (staggeredGridLayoutManager.getSpanCount() == 1) {
lastVisibleItem = lastVisibleItems[0];
} else if (staggeredGridLayoutManager.getSpanCount() == 2) {
lastVisibleItem = Math.max(lastVisibleItems[0], lastVisibleItems[1]);
} else if (staggeredGridLayoutManager.getSpanCount() == 3) {
lastVisibleItem = Math.max(Math.max(lastVisibleItems[0], lastVisibleItems[1]), lastVisibleItems[2]);
}
if (!isRefreshing && (totalItemCount <= lastVisibleItem + visibleThreshold)) {
Log.d(Const.DEBUG, "isRefreshing: " + isRefreshing);
Log.d(Const.DEBUG, "totalItemCount: " + totalItemCount);
Log.d(Const.DEBUG, "lastVisibileItem: " + lastVisibleItem);
Log.d(Const.DEBUG, "visibileThreshold: " + visibleThreshold);
Log.d(Const.DEBUG, "calling LoadMore()");
if (mIOnLoadMoreListener != null) {
mIOnLoadMoreListener.onLoadMore();
}
isRefreshing = true;
}
}
});
}
I get 9 values from server on first call. So, when i move to the last index[8], the lastVisibleItem will be 8 and visibleThreshold is 1, totalItemCount is 9 and so the next network call should happen. What is actually happening now, is, when the screen loads for the first time, the lastVisibleItem should be 1 or 2, but its returning 8, and as a result, the loadMore() is getting called.
Logcat:
D/xx: Items Count: 9
D/xx: LastVisibleItems: [8]
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: LastVisibleItems Count: 1
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: isRefreshing: false
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: totalItemCount: 9
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: lastVisibileItem: 8
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: visibileThershold: 1
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: calling LoadMore()
03-22 15:22:52.772 5957-5957/codsiga.com.xx D/xx: onLoadMore()
03-22 15:22:52.798 5957-5957/codsiga.com.xx D/xx: getDataFromServer()
What is wrong in the above code? Let me know if you need anything else. The same code worked well before.
Try this.
private int pastVisiblesItems, visibleItemCount, totalItemCount;
private boolean loading = true;
private StaggeredGridLayoutManager layoutManager;
private RecyclerView recyclerView ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layoutManager=new StaggeredGridLayoutManager(2,1);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(layoutManager);
recycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (dy > 0) //for vertical scrolling
{
} else if (dy < 0) {
}
if (dx > 0)//for horizontal scrolling
{
visibleItemCount = layoutManager.getChildCount();
totalItemCount = layoutManager.getItemCount();
pastVisiblesItems = layoutManager.findFirstVisibleItemPosition();
if (loading) {
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading = false;
loadMore(); //desired function call
}
}
}
}
});
}
Please don't forget to make loading=true after the success of API calling.
Hope it may help..
following code is work for me :
//return true if it's last item visited
private boolean isLastItemDisplaying(RecyclerView recyclerView) {
if (recyclerView.getAdapter().getItemCount() != 0) {
//int lastVisibleItemPosition = ((StaggeredGridLayoutManager)recyclerView.getLayoutManager()).findLastVisibleItemPositions();
int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) Objects.requireNonNull(recyclerView.getLayoutManager())).findLastVisibleItemPositions(null);
// get maximum element within the list
int lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
return lastVisibleItemPosition != RecyclerView.NO_POSITION && lastVisibleItemPosition == recyclerView.getAdapter().getItemCount() - 1;
}
return false;
}
//get last item
public int getLastVisibleItem(int[] lastVisibleItemPositions) {
int maxSize = 0;
for (int i = 0; i < lastVisibleItemPositions.length; i++) {
if (i == 0) {
maxSize = lastVisibleItemPositions[i];
} else if (lastVisibleItemPositions[i] > maxSize) {
maxSize = lastVisibleItemPositions[i];
}
}
return maxSize;
}
private void recyclerViewOnScroll(RecyclerView recyclerView, final StaggeredGridLayoutManager staggeredGridLayoutManager) {
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (dy > 0) {
totalItemCount = staggeredGridLayoutManager.getItemCount();
if (lastPositions == null)
lastPositions = new int[staggeredGridLayoutManager.getSpanCount()];
lastPositions = staggeredGridLayoutManager.findLastCompletelyVisibleItemPositions(lastPositions);
lastVisibleItem = Math.max(lastPositions[0], lastPositions[1]);//findMax(lastPositions);
if (!loading && totalItemCount >= 20 && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
// End has been reached
if (onLoadMoreListener != null) {
onLoadMoreListener.onLoadMore();
}
loading = true;
}
}
}
});
}
I'm trying to implement Endless Recyclerview in android and able to load the next set of data On scroll of RecyclerView.
But once I receive new set of data , my recycler activity is getting reloaded and items are displaying from initial data . I have even tried with EndlessScrollRecyclListener, but it was same.
Here is the code i'm trying
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = mRecyclerView.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && (totalItemCount - visibleItemCount)
<= (firstVisibleItem + visibleThreshold)) {
// End has been reached
new LoadData().execute(0);
loading = true;
}
}
});
I try implement staggered RecyclerView. I create Abstract onScroll RecyclerView Like this :
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int grid_column_count = context.getResources().getInteger(R.integer.grid_column_count);
StaggeredGridLayoutManager mLayoutManager = new StaggeredGridLayoutManager(grid_column_count, StaggeredGridLayoutManager.VERTICAL);
int visibleItemCount = recyclerView.getChildCount();
int totalItemCount = mLayoutManager.getItemCount();
int firstVisibleItemsGrid[] = new int[grid_column_count];
int firstVisibleItem = mLayoutManager.findFirstVisibleItemPositions(firstVisibleItemsGrid)[0];
if ((visibleItemCount + firstVisibleItem ) >= totalItemCount
&& totalItemCount != 0) {
onLoadingMore();
}
}
protected abstract void onLoadingMore();
and I implenting by MainActity
//===============
recyclerview= (RecyclerView)rootView. findViewById(R.id.grid_view);
recyclerview.setHasFixedSize(true);
grid_column_count = getResources().getInteger(R.integer.grid_column_count);
mLayoutManager = new StaggeredGridLayoutManager(grid_column_count, StaggeredGridLayoutManager.VERTICAL);
recyclerview.setLayoutManager(mLayoutManager);
//=====================
recyclerview.addOnScrollListener(new HidingScrollListener(getActivity()) {
#Override
protected void onLoadingMore() {
if ( isFinishLoadingAwal
&& !isFinishMoreNews
&& adapter.getItemCount()> 0) {
getMoreNewsFromServer();
}
}
});
But I getting error in line :
firstVisibleItem = mLayoutManager.findFirstVisibleItemPositions(firstVisibleItemsGrid)[0];
log :
Process: com.ad.kamardagang, PID: 23350
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.support.v7.widget.OrientationHelper.getStartAfterPadding()' on a null object reference
at android.support.v7.widget.StaggeredGridLayoutManager$Span.findOneVisibleChild(StaggeredGridLayoutManager.java:2337)
at android.support.v7.widget.StaggeredGridLayoutManager$Span.findFirstVisibleItemPosition(StaggeredGridLayoutManager.java:2313)
at android.support.v7.widget.StaggeredGridLayoutManager.findFirstVisibleItemPositions(StaggeredGridLayoutManager.java:826)
at com.ad.kamardagang.utils.HidingScrollListener.onScrolled(HidingScrollListener.java:90)
at android.support.v7.widget.RecyclerView.dispatchOnScrolled(RecyclerView.java:3674)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2824)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3011)
at android.view.View.layout(View.java:15671)
so how to fix it ? or any solution ?
sorry for my english.
I use this Mugen for endless scrolling for StaggeredGrid with RecyclerView.
Replace firstVisibleItem = mLayoutManager.findFirstVisibleItemPositions(firstVisibleItemsGrid)[0]; with
firstVisibleItem = ((LinearLayoutManager)recyclerView.getLayoutManager()).findFirstVisibleItemPosition(); and try.