3

I'm trying to implement a skipping feature in my vertical recyclerview. When a user clicks a button, the recyclerView will scroll all the way to the bottom and trigger an API call. Right now to check if the user is at the bottom of the screen, I am using .addOnScrollListener on my recyclerview.

mGridRecycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

                //SCROLL_STATE_IDE prevents repeated calls from happening
                // when near bottom of screen and slightly scroll up a bit
                if(!mGridRecycler.canScrollVertically(1) && newState==RecyclerView.SCROLL_STATE_IDLE){
                    Log.d(TAG, "onScrollStateChanged: CALLED WTF");
                    mActivity.getNextPageGridView();
                }
            }
        });

And to implement the skipping feature to the last item, I am using this method on a button:

mGridRecycler.scrollToPosition(mList.size() - 1);

It skips to the last item, however the API call is not triggered because the if-statement is not called. Anyone know what I can make it work successfully?

DIRTY DAVE
  • 2,523
  • 2
  • 20
  • 83

4 Answers4

2

RecyclerView does not know how LayoutManager will handle the scroll.
You'll only receive a call to onScrolled if first and or last child position changes after a layout, you're not gonna get onScrollStateChanged callback.

What should you do?

Alternatively you can use smoothScrollToPosition(..) method, OR override onScrolled method, OR make a request to your API right after the skip button click, which is the best solution for your scenario.

Tiko
  • 990
  • 7
  • 18
  • I changed it to ```.smoothScrollToPosition``` and the API call is now working when I skip. Thanks for explaining. – DIRTY DAVE Feb 28 '20 at 21:43
0

It will not scroll to the end of your layout if your content layout had a top margin or your item view have margin. I don't remember exactly but try to remove all margin of itemview and contentview. I solved the problem with a little hack, adding an empty view to the end of the LinearLayout earlier in my project.

Nimantha
  • 6,405
  • 6
  • 28
  • 69
Thành Hà Văn
  • 481
  • 2
  • 9
0

Recylerview scrolling is very fast so try to give a delay of 1 sec using handler or you can also use

recyclerView.post(() -> mGridRecycler.scrollToPosition(mList.size() - 1);
0

In order to properly implement an auto smooth scrolling you need to do the following:

Declare a scroll speed constant:

companion object {
    const val SMOOTH_SCROLL_SPEED = 100f
}

Create a global SmoothScroller param:

private lateinit var smoothScroller: SmoothScroller

In your init method: Initialize the SmoothScroller object:

smoothScroller = object : LinearSmoothScroller(context) {
    override fun getVerticalSnapPreference(): Int {
        return SNAP_TO_START
    }

    override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics?): Float {
        displayMetrics?.let {
            return SMOOTH_SCROLL_SPEED / it.densityDpi
        }
        return super.calculateSpeedPerPixel(displayMetrics)
    }
}

Create this method and call it whenever you wish to smoothScroll to any position in the list:

open fun smoothScroll(position: Int) {
    smoothScroller.targetPosition = position
    yourRecycleView.layoutManager.startSmoothScroll(smoothScroller)
}
Nimantha
  • 6,405
  • 6
  • 28
  • 69
orimen
  • 571
  • 4
  • 11