7

I am trying to do endless recycler view, using pagination in a fragment .
But facing problems as follows.

  1. findLastCompletlyVisibleItemPosition() or findFirstCompletelyVisibleItemPosition() is returning only -1.
  2. if setNestedScrollingEnabled(false), then onScrollStateChanged is not working

Below is a sample of my code. `

        recyclerView = (RecyclerView) view.findViewById(R.id.recycler1);

        //recyclerView.setNestedScrollingEnabled(false);                                              // Smooth Scrolling
         mLayoutManager = new LinearLayoutManager(getActivity());

        lastVisiblePosition = mLayoutManager.findLastVisibleItemPosition();
        firstVisibleItemPosition = mLayoutManager.findFirstCompletelyVisibleItemPosition();
        Log.i("sandi", String.valueOf(firstVisibleItemPosition));
        load = new LoadAdapter(getActivity(), grid_list);
        recyclerView.setLayoutManager(mLayoutManager);
        recyclerView.setItemAnimator(new DefaultItemAnimator());
        recyclerView.setAdapter(load);
        mProgressDialog.dismiss();

        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                int threshold =1;
                int count = recyclerView.getChildCount();



                Log.i("sand", String.valueOf(count));

                if (newState == SCROLL_STATE_IDLE ) {
                    if (lastVisiblePosition >= count
                            - threshold) {
                        // Execute LoadMoreDataTask AsyncTask

                        Log.i("sand","stopped");
                        new LoadMoreDataTask().execute();
                    }
                } else {
                    Log.i("sand","not stopped");
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
            }
        });
    }

EDIT
The solution of this problem is in the comments section.

Saurabh
  • 136
  • 1
  • 1
  • 11

3 Answers3

6

Look into line no 1732 to 1747 in LinearLayoutManager

/**
 * Returns the adapter position of the last fully visible view. This position does not include
 * adapter changes that were dispatched after the last layout pass.
 * <p>
 * Note that bounds check is only performed in the current orientation. That means, if
 * LayoutManager is horizontal, it will only check the view's left and right edges.
 *
 * @return The adapter position of the last fully visible view or
 * {@link RecyclerView#NO_POSITION} if there aren't any visible items.
 * @see #findLastVisibleItemPosition()
 * @see #findFirstCompletelyVisibleItemPosition()
 */

public int findLastCompletelyVisibleItemPosition() {
    final View child = findOneVisibleChild(getChildCount() - 1, -1, true, false);
    return child == null ? NO_POSITION : getPosition(child);
}

Here if child is null than you will have NO_POSITION which is -1.

What you are doing:

You are calling below before setting your adapter. There is no View available so you have -1.

lastVisiblePosition = mLayoutManager.findLastVisibleItemPosition();
firstVisibleItemPosition = mLayoutManager.findFirstCompletelyVisibleItemPosition();

What you should do:

Your can have findLastVisibleItemPosition and findFirstCompletelyVisibleItemPosition when your adapter's view is completely populate. First set your adapter than get your positions like

load = new LoadAdapter(getActivity(), grid_list);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(load);
mProgressDialog.dismiss();
// adapter is set now you may have your positions
lastVisiblePosition = mLayoutManager.findLastVisibleItemPosition();
firstVisibleItemPosition = mLayoutManager.findFirstCompletelyVisibleItemPosition();
Log.i("sandi", String.valueOf(firstVisibleItemPosition));
Haris Qurashi
  • 2,104
  • 1
  • 13
  • 28
  • it worked, but by putting lastVsible and firstVisible position inside onScrollStateChanged. And can you please explain why onScrollStateChanged is not working when ,recyclerView.setNestedScrollingEnabled(false); – Saurabh Dec 09 '16 at 08:46
  • That's why i added a comment you may have your positions, yes you should get `lastVisiblePosition` and `firstVisibleItemPosition` when your view is completely populated. – Haris Qurashi Dec 09 '16 at 09:08
  • And can you please explain why onScrollStateChanged is not working when ,recyclerView.setNestedScrollingEnabled(false); – Saurabh Dec 09 '16 at 09:11
  • why do you need to set `recyclerView.setNestedScrollingEnabled(false)`? – Haris Qurashi Dec 09 '16 at 09:13
  • for smooth scrolling.I think because it is inside nested scrollview.And scrolling is not smooth if i don't put recyclerView.setNestedScrollingEnabled(false). – Saurabh Dec 09 '16 at 09:17
  • Use `recyclerView.setNestedScrollingEnabled(false)` when your recyclerView's parent is `ScrollView` or `NestedScrollView`. Otherwise you don't need this – Haris Qurashi Dec 09 '16 at 09:19
  • This didn't help, I am adding listener AFTER assigning adapter, but to no luck. Any other ideas? – obey Jan 01 '21 at 17:31
1

I struggled with the same issue for hours, It seems you need to add a globallayoutlistener on your recycler view and put your code in the callback.

odich daniel
  • 87
  • 2
  • 12
0

If you are using a recyclerview inside a NestedScrollView, recyclerView.addOnScrollListener is not triggered. I figured that out while trying to implement pagination as well. Instead of that I have implemented onScrollChangeListener for NestedScrollView and does the trick with the following code:

private void implementScrollListener() {

    //Scroll Listener for nestedScrollView. Note that it is used for pagination when user reaches the bottom.

    if(nestedScrollView != null){

        nestedScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
            @Override
            public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {

                if (scrollY > oldScrollY) {
                    //Scrolling down
                }
                if (scrollY < oldScrollY) {
                    //Scrolling up
                }

                if (scrollY == 0) {
                    //Reaches to the top
                }

                if (scrollY < (v.getChildAt(0).getMeasuredHeight() - v.getMeasuredHeight())) {
                    //Reaches to the bottom so it is time to updateRecyclerView!
                    updateRecyclerView();
                }
            }
        });
    }

}`
Baki Kocak
  • 389
  • 1
  • 9