'How to prevent touches prematurely stopping smoothScroll in RecyclerView?

I am using an Adapter to fill a RecyclerView with numerous CardView layouts (horizontally). Each CardView has a Button at the bottom of the layout, which when pressed prompts the call:

recyclerView.smoothScrollBy(x, y);

This scrolls horizontally to the next card as expected, unless the user touches the screen as it is scrolling. I have attempted disabling the TouchEvent for the RecyclerView and the CardView to no avail.

I obviously cannot rely on a user to not touch the screen during this scrolling animation, so I was wondering if anyone had any ideas as to why the scrolling is halted prematurely and how I can stop it.

img

Thanks.



Solution 1:[1]

problem is onInterceptTouchEvent

if you add listener to recyclerView this way:

    addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
        override fun onInterceptTouchEvent(rv: RecyclerView, e: MotionEvent): Boolean {
            return true
        }
    })
  1. if it is return true you can't scroll recyclerView manually (programmatically you can)
  2. if it is return true scrolling is stopped/interrupted

this option worked for me (add this to recyclerView with previous code snippet (to prevent manual scrolling) to prevent scrolling interrupt on touch):

override fun onInterceptTouchEvent(e: MotionEvent): Boolean {
    if (layoutManager?.isSmoothScrolling == true || scrollState == SCROLL_STATE_SETTLING) {
        return true
    }
    return super.onInterceptTouchEvent(e)
}

override fun onTouchEvent(e: MotionEvent): Boolean {
    if (layoutManager?.isSmoothScrolling == true || scrollState == SCROLL_STATE_SETTLING) {
        return true
    }
    return super.onTouchEvent(e)
}

Solution 2:[2]

Disable user interactions before the scroll and reenable them a little after. I would use window flags:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);

recyclerView.smoothScrollBy(x, y);

new Handler().postDelayed(new Runnable() {
   public void run(){
      getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
   }
}, 500);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 NataTse
Solution 2 RĂ³bert Szalai