16

Recyclerview right now has 3 states.

SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING

An issue raised for the same to include a fling state.I cannot determine if anything was done regarding this.

Is there a way to differentiate between a Drag and a Fling in recyclerview.

EDIT: The requirement for such functionality: When the user flings,I want to be able to pause loading images(all images are url requests) in the recycler view and resume once he reaches an item of interest,thereby ensuring that the image he is currently viewing loads before the others.

Droidekas
  • 3,464
  • 2
  • 26
  • 40
  • As far as I could tell from the issue and the current source code, there is no easy way to do it. There are alternatives though. What are you trying to accomplish? – Ricardo Feb 07 '16 at 13:24
  • That would be a really long reason.But overall I need to perform a process,on the current item after the user flings through. – Droidekas Feb 07 '16 at 18:30
  • When the user flings what? One of the items? Down or up the Recycler view? Is he swiping it away an item, like dismissing it? What happens on the UI to show that the user did a fling besides stopping all the image loading? – Ricardo Feb 08 '16 at 06:31
  • Up/Down on the recycler view . That constitutes a fling,an item interaction would be called a swipe ?And nothing else happens on the UI.This is only to prevent unnecessary API calls – Droidekas Feb 08 '16 at 06:33
  • And why didn't the `GestureDetector` work for you? – Ricardo Feb 08 '16 at 06:40

3 Answers3

8

SCROLL_STATE_FLING : No longer a part of RecyclerView as it is not mentioned in documentation here

Regarding your requirement :

RecyclerView is inside android.view.ViewGroup and as per its source code it extends ViewGroup documentation here .

The scrolling in a RecyclerView is sort of split up between the RecyclerView and the LinearLayoutManager. There are two cases that needed to handle:

  1. The user flings the view. The default behavior is that the RecyclerView passes the fling to an internal Scroller which then performs the scrolling magic. This is problematic because then the RecyclerView usually settles in an unsnapped position. Solve this by overriding the RecyclerView fling() implementation and instead of flinging, smoothscroll the LinearLayoutManager to a position.
  2. The user lifts their finger with insufficient velocity to initiate a scroll. No fling occurs in this case. If you want to detect this case in the event that the view is not in a snapped position, you can do this by overriding the onTouchEvent method.

See here for detail Snappy scrolling in RecyclerView

A few ViewPager hints that are worth mentioning as RecyclerView is a child of it:

  1. Think about modifying the number of pages that are cached. This is especially important when you only have 3 or 4 pages. The default setting will store 1 page either side of the current page. In the scenario that you have 3 pages, swiping to the middle page will mean that all of your pages will be cached. Then swiping to the first or last page will drop one of the pages out of memory and they will need to be recreated and re-added when you swipe back again. By setting setOffscreenPageLimit(2) you’ll allow all of your pages to stay in memory all the time. This is a trade off between performance and memory considerations, so it is a good idea to listen for low memory warnings and be prepared to remove edge pages if necessary.

  2. If you’re trying to replace Views in your ViewPager, it isn’t enough just to change the data set behind the adapter and call notifyDataSetChanged(). You also need to ensure that you’ve correctly implemented getItemPosition(Object object) and return POSITION_NONE for items that have changed and return POSITION_UNCHANGED or the actual position for items that haven’t changed.

  3. Another API that was added is setPageMargin() and setPageMarginDrawable(), allowing you to easily separate your pages.

See here for detail Horizontal View Swiping with ViewPager, Updated

Difference between a Drag and a Fling

For Drag feature You can use some of the RecyclerView's companion classes:

  1. ItemTouchHelper, which is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.

  2. its ItemTouchHelper.Callback, which is the contract between ItemTouchHelper and your application

For fling you can see

  1. Android fling actions on a RecyclerView

  2. Android : Control Smooth scroll over recycler view

tochkov
  • 2,917
  • 2
  • 15
  • 21
Mohammad Tauqir
  • 1,817
  • 1
  • 18
  • 53
6

I use a combination of SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING to do this: here is my code:

@Override
            public void onScrollStateChanged(int newState) {
                if (newState == RecyclerView.SCROLL_STATE_DRAGGING || newState == RecyclerView.SCROLL_STATE_SETTLING) {
                    if (mAdapter != null)
                        mAdapter.pauseImageLoading();
                } else if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    if (mAdapter != null)
                        mAdapter.resumeImageLoading();
                }

this works for me same as you want it resume when user stop at item of interest

JAAD
  • 12,349
  • 7
  • 36
  • 57
  • 1
    I tried this,it doesnt work in the case: you stop the scroll suddenly,the item you are on does not load because that request has been rejected as a part of the scroll – Droidekas Feb 13 '16 at 17:59
1

Your problem could be potentially solved in a different way. You could try to defer your requests by a couple hundred milliseconds (exact number would need to be tweaked). If the list item scrolls offscreen within those milliseconds, you can cancel the request before it is sent. The idea being that if you fling, the views will scroll offscreen so quickly that requests will always be cancelled before they are sent. If they are not flinging, those extra milliseconds per request hopefully isn't too bad of an experience.

Bradley Campbell
  • 9,298
  • 6
  • 37
  • 47