I'm trying to implement pagination using code below, and it work well with fragments, but when i implemented it in Nested Fragment it load all data (load first page and all next pages continuously). The problem is that my total items is 12 and visible in time is 3 but layoutManager.getChildCount() give me 12 same as total item (layoutManager.getItemCount()) so it start loading next pages continuously.
Here is oNScroll code :
public PaginationScrollListener(LinearLayoutManager layoutManager) {
this.layoutManager = layoutManager;
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = layoutManager.getChildCount();
int totalItemCount = layoutManager.getItemCount();
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
if (!isLoading() && !isLastPage()) {
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount
&& firstVisibleItemPosition >= 0
&& totalItemCount >= getTotalPageCount()) {
loadMoreItems();
}
}
}
When scroll and request next pages :
recyclerView.addOnScrollListener(new PaginationScrollListener(layoutManager) {
#Override
protected void loadMoreItems() {
isLoading = true;
currentPage += 1;
// mocking network delay for API call
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
loadNextPage();
}
}, 1000);
}
#Override
public int getTotalPageCount() {
return TOTAL_PAGES;
}
#Override
public boolean isLastPage() {
return isLastPage;
}
#Override
public boolean isLoading() {
return isLoading;
}
});
change your scroll listener like below:
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if(dy>0){ //if is scrolling vertically
int visibleItemCount = layoutManager.getChildCount();
int totalItemCount = layoutManager.getItemCount();
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
if (!isLoading() && !isLastPage()) {
if (firstVisibleItemPosition + visibleItemCount >= totalItemCount) {
//make your request here
}
}
}});
Related
My recyclerview.Onscrolled() method is getting called only once.
When I am trying to scroll down, it not getting scrolled and onSCrolled method is not getting called
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
boolean loading = true;
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy)
{
if (loading) {
if (dy > 0) //check for scroll down
{
int visibleItemCount = 6;
int totalItemCount = posts.size();
int pastVisiblesItems = mLayoutManager.findFirstVisibleItemPosition();
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
loading = false;
Log.v("...", " Reached Last Item");
int size = mAdapter.getTodoList().size();
mAdapter.getTodoList().clear();
mAdapter.setTodoList(getNextItems(mAdapter.getResult(),size));
mAdapter.notifyItemRangeInserted(size, mAdapter.getTodoList().size() - 1);
}
}
}
}
});
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 applied on scroll in listview the following way:
mylistview.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
boolean loadMore = /* maybe add a padding */
firstVisibleItem + visibleItemCount >= totalItemCount;
if(loadMore) {
int tempLimit = totalItemCount/50 + 1;
FriendsAdapter temp = (FriendsAdapter) friendsList.getAdapter();
if (temp!=null&&temp.ev.size()>0&&temp.ev.size()+50<=tempLimit*50) {
limit = tempLimit;
new GetFriendRequestsAsync(getActivity(),String.valueOf(limit)).execute();
}
}
}
});
Now I need to update that and use a RecycleView. How can I apply this to a RecycleView? Every 50 items, I do something.
You can use the following:
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
boolean loadMore = /* maybe add a padding */
lastVisibleItemPosition + 6 >= totalItemCount;
if (loadMore) {
int tempLimit = totalItemCount / 50 + 1;
FriendsAdapter temp = (FriendsAdapter) friendsList.getAdapter();
if (temp != null && temp.ev.size() > 0 && temp.ev.size() + 50 <= tempLimit * 50) {
limit = tempLimit;
new GetFriendRequestsAsync(getActivity(), String.valueOf(limit)).execute();
}
}
}
});
I use the following code to implement the infinite scroll. but the problem is the onScroll() method keeps calling continuously and loading data falls to an endless loop. what am I missing here?
public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener {
public int previousTotal = 0; // The total number of items in the dataSet after the last load
public boolean loading = true; // True if we are still waiting for the last set of data to load.
public int visibleThreshold = 0; // The minimum amount of items to have below your current scroll position before loading more.
int firstVisibleItem, visibleItemCount, totalItemCount;
public 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) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
current_page++;
onLoadMore(current_page);
loading = true;
}
}
public abstract void onLoadMore(int current_page);
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
}
and in my activity:
endlessRecyclerOnScrollListener = new EndlessRecyclerOnScrollListener(mLayoutManager) {
#Override
public void onLoadMore(int current_page) {
loadData()
}
};
mRecyclerView.addOnScrollListener(endlessRecyclerOnScrollListener);
This is how I did endless scrolling and it works perfect for me. Thanks...
private boolean loading = true;
int pastVisiblesItems, visibleItemCount, totalItemCount;
LinearLayoutManager mLayoutManager;
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
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("...", "We reach Last Item!");
// fetch new data here or whatever you want.
DoPagination();
}
}
}
}
});
I have been searching for a while but can't find a solution to detect end of scroll of recycler view with grid layout manager. Using code below actually work, but it is for linear layout manager not for grid layout manager.
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int scrollState) {
final int treeshold = 0;
try {
if (scrollState == RecyclerView.SCROLL_STATE_IDLE) {
if (((LinearLayoutManager) recyclerView.getLayoutManager()).findLastVisibleItemPosition() >= yourData.size()
- 1 - treeshold) {
//your load more logic
}
}
} catch (Exception e) {
}
}
The idea is that i want to implement load more function to my application, so i need to detect end of scroll.
Edit : maybe the problem not the grid view itself. I used com.tonicartos.superslim library to get sticky header view. I wonder that it might be the problem
Add a scroll listener to your RecyclerView like below:
int pastVisiblesItems, visibleItemCount, totalItemCount;
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView,
int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = layoutManager.getChildCount();
totalItemCount = layoutManager.getItemCount();
pastVisiblesItems = layoutManager.findFirstVisibleItemPosition();
if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
//bottom of recyclerview
}
}
});
layoutmanager is your GridLayoutManager
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 = 5; // The minimum amount of items to have below your current scroll position before loading more.
int firstVisibleItem, visibleItemCount, totalItemCount;
private int currentPage = 1;
private RecyclerView.LayoutManager mLayoutManager;
private boolean isUseLinearLayoutManager;
private boolean isUseGridLayoutManager;
public EndlessRecyclerOnScrollListener(LinearLayoutManager linearLayoutManager) {
this.mLayoutManager = linearLayoutManager;
isUseLinearLayoutManager = true;
}
public EndlessRecyclerOnScrollListener(GridLayoutManager gridLayoutManager) {
this.mLayoutManager = gridLayoutManager;
isUseGridLayoutManager = true;
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = recyclerView.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
if(isUseLinearLayoutManager && mLayoutManager instanceof LinearLayoutManager){
firstVisibleItem = ((LinearLayoutManager) mLayoutManager).findFirstVisibleItemPosition();
}
if(isUseGridLayoutManager && mLayoutManager instanceof GridLayoutManager){
firstVisibleItem = ((GridLayoutManager) mLayoutManager).findFirstVisibleItemPosition();
}
if (loading) {
if (totalItemCount > previousTotal) {
loading = false;
previousTotal = totalItemCount;
}
}
if (!loading && (totalItemCount - visibleItemCount)
<= (firstVisibleItem + visibleThreshold)) {
// End has been reached
// Do something
currentPage++;
onLoadMore(currentPage);
loading = true;
}
}
public abstract void onLoadMore(int currentPage);
I just sent an email directly to Mr. Artos about this problem and got a reply:
"It likely won't work properly until the next version is finished. I wrote about it on my blog at http://www.tonicartos.com/2015/12/superslim-milestone-1_23.html?m=1"