317

I cannot disable scrolling in the RecyclerView. I tried calling rv.setEnabled(false) but I can still scroll.

How can I disable scrolling?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Zsolt Safrany
  • 13,290
  • 6
  • 50
  • 62
  • 3
    What is the point of using `RecyclerView` if you do not want scrolling? – CommonsWare May 29 '15 at 14:16
  • 24
    @CommonsWare, I just want to disable it temporarily, for instance, while I'm doing a custom animation with one of its children. – Zsolt Safrany May 29 '15 at 14:18
  • 2
    Ah, OK, that makes sense. I'd've probably put a transparent `View` over top of the `RecyclerView`, toggling between `VISIBLE` and `GONE` as needed, but off the cuff your approach seems reasonable. – CommonsWare May 29 '15 at 14:21
  • Hope [this](http://stackoverflow.com/questions/30222310/disable-scrolling-in-child-recyclerview-android) helps find a better solution. – Saiteja Parsi Sep 24 '15 at 19:25
  • 1
    @CommonsWare, here's what I need it for, for example. I need to display images in RecyclerView one at a time, without partially visible images, only one in my viewport. And there are arrows on the left and on the right which user can navigate with. Depending on what image is currently displayed (they are of various types), some things outside RecyclerView are triggered. It's the design our customers want. – Varvara Kalinina May 05 '16 at 10:50
  • @CommonsWare I need to disable scrolling to also have up/down swipe directions. I use grid layout, not a list, and the items are all sized such that they are visible on the screen. – frangulyan Nov 06 '16 at 14:34
  • Id I want to dynamically displaying all items of the recycle view under a big scrollview, then disabling the scrolling is helpful . – Jeff Bootsholz Nov 19 '18 at 02:01
  • 1
    IMO there is a lot of use in using a RecyclerView without scroll. Maybe this is just me but the RecyclerView adapter offers a simple way to dynamically inflate different types of views with memory efficiency. I do have a custom LinearLayout , but it requires a lot more code to handle lifecycles, viewTypes, items ID's and ListDIffer adapters... with custom animations...etc... Also a list is almost always accompanied by a header with titles and menus, etc.. and all of those items are most certainly part of the List in a bigger scrollable view. – Delark May 04 '21 at 00:21

33 Answers33

465

You should override the layoutManager of your recycleView for this. This way it will only disable scrolling, none of the other functionalities. You will still be able to handle click or any other touch events. For example:-

Original:

public class CustomGridLayoutManager extends LinearLayoutManager {
    private boolean isScrollEnabled = true;

    public CustomGridLayoutManager(Context context) {
        super(context);
    }

    public void setScrollEnabled(boolean flag) {
        this.isScrollEnabled = flag;
    }

    @Override
    public boolean canScrollVertically() {
        //Similarly you can customize "canScrollHorizontally()" for managing horizontal scroll
        return isScrollEnabled && super.canScrollVertically();
    }
}

Here using "isScrollEnabled" flag you can enable/disable scrolling functionality of your recycle-view temporarily.

Also:

Simple override your existing implementation to disable scrolling and allow clicking.

linearLayoutManager = new LinearLayoutManager(context) {
    @Override
    public boolean canScrollVertically() {
        return false;
    }
};

In Kotlin:

object : LinearLayoutManager(this) { override fun canScrollVertically() = false }
kingston
  • 11,053
  • 14
  • 62
  • 116
Saurabh Garg
  • 4,694
  • 1
  • 11
  • 8
211

The real answer is

recyclerView.setNestedScrollingEnabled(false);

More info in documentation

Bozic Nebojsa
  • 3,606
  • 1
  • 19
  • 17
  • 54
    This will only disable nested scrolling, not all scrolling. In particular, if your RecyclerView is in a ScrollView but does not fill the screen, the ScrollView will not scroll (content fits in screen), and you will get the scroll UI in your RecyclerView (end of list effect when trying to scroll for example) even though it will not scroll when it gets bigger. Extending the LayoutManager really does the job. – personne3000 Mar 17 '16 at 04:58
  • 3
    @personne3000 I believe recyclerView.setHasFixedSize(true) does the job for that. Edit: I also use this in conjuction with setFillViewport(true) so I'm not actually sure which one of the two fixes it. – mDroidd Aug 12 '16 at 10:59
  • 8
    This works fine for me, but my "RecyclerView" was inside a Fragment layout using "ScrollView", so I had to change the "ScrollView" by "NestedScrollView", as described here: https://stackoverflow.com/a/38088902/618464 – educoutinho Nov 18 '17 at 13:15
  • 1
    Remember to use the full class name for `NestedScrollView`: `android.support.v4.widget.NestedScrollView`, as described here, by chessdork: https://stackoverflow.com/questions/37846245/error-inflating-class-nestedscrollview-class-not-found – gustavoknz Aug 31 '18 at 03:31
  • After spending 4 hours to trying to figure out what is wrong this solved my issue. In my case I am using a recyclerview inside of a MotionLayout. And I only added a swipe area to drag up by adding motion:touchAnchorId="@id/swipe_area". It works normally but also triggered when touched recyclerview's empty areas. Be careful when using motionLayout with other swipable elements. – O. Kumru May 28 '19 at 22:27
  • This is the best answer for my case, the `LinearLayoutManager.canScrollVertically()` do not work same way as this. This method dispatched touch event to it parent view to handle. – ganiular Sep 26 '22 at 02:51
167

For API 21 and above:

No java code needed. You can set android:nestedScrollingEnabled="false" in xml:

<android.support.v7.widget.RecyclerView
     android:id="@+id/recycler"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:clipToPadding="true"
     android:nestedScrollingEnabled="false"
     tools:listitem="@layout/adapter_favorite_place">
Milad Faridnia
  • 9,113
  • 13
  • 65
  • 78
59

This a bit hackish workaround but it works; you can enable/disable scrolling in the RecyclerView.

This is an empty RecyclerView.OnItemTouchListener stealing every touch event thus disabling the target RecyclerView.

public class RecyclerViewDisabler implements RecyclerView.OnItemTouchListener {

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        return true;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {

    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
}

Using it:

RecyclerView rv = ...
RecyclerView.OnItemTouchListener disabler = new RecyclerViewDisabler();

rv.addOnItemTouchListener(disabler);        // disables scolling
// do stuff while scrolling is disabled
rv.removeOnItemTouchListener(disabler);     // scrolling is enabled again 
worked
  • 5,762
  • 5
  • 54
  • 79
Zsolt Safrany
  • 13,290
  • 6
  • 50
  • 62
  • 10
    Does this disable the item clicking too? – Jahir Fiquitiva Jul 15 '15 at 03:41
  • 1
    @JahirFiquitiva Yes. "This is an empty RecyclerView.OnItemTouchListener stealing every touch event" – Max Aug 21 '15 at 12:14
  • 2
    this also disables parent view's scroll as well – Jemshit Sep 03 '15 at 08:46
  • This disables item click too – Muhammad Riyaz Dec 07 '15 at 09:27
  • 1
    Why use a hackish workaround (with side effects) when there is a clean solution ? Just override the LayoutManager (see other answers) – personne3000 Mar 17 '16 at 04:59
  • @personne3000 I chose this solution over the accepted answer because it only blocks inputs from the user, and still allows me to call the smoothScrollBy() method. So I can disable user scrolling, run some animations in the recyclerview, and re-enable it afterwards. – elliptic1 Oct 06 '16 at 20:24
  • Instead of returning true, and therefore disabling all sorts of touch events, just `return e.getAction() == MotionEvent.ACTION_MOVE;` instead of `return true;` so only scroll/swipe events get cancelled. – Toufic Batache Jul 19 '19 at 21:49
47

This works for me:

  recyclerView.setOnTouchListener(new View.OnTouchListener() {
      @Override
      public boolean onTouch(View v, MotionEvent event) {
          return true;
      }
  });
sergej shafarenka
  • 20,071
  • 7
  • 67
  • 86
alxgarcia
  • 495
  • 4
  • 5
  • 17
    This disables all touch. – Jared Burrows Jan 09 '16 at 21:35
  • 1
    Nice trick! To re-enable again, just re-set the onTouchListener's onTouch to return false – HendraWD Jul 03 '17 at 07:45
  • uhm, but there is a warning `Custom view 'RecyclerView' has setOnTouchListener called on it but does not override performClick` – HendraWD Jul 03 '17 at 07:59
  • If you are receiving the same warning that @HendraWD mentioned in the comment above then take a look at this question's answers: https://stackoverflow.com/questions/46135249/custom-view-imagebutton-has-setontouchlistener-called-on-it-but-does-not-overr – Nicolás Carrasco-Stevenson Dec 14 '17 at 20:09
  • 1
    Instead of returning true, and therefore disabling all sorts of touch events, just `return e.getAction() == MotionEvent.ACTION_MOVE;` instead of `return true;` so only scroll/swipe events get cancelled. – Toufic Batache Jul 19 '19 at 21:50
  • Kotlin short version products_carousel.setOnTouchListener { _, _ -> true} – Arsenius Sep 17 '20 at 11:39
26

As setLayoutFrozen is deprecated, You can disable scrolling by freezing your RecyclerView by using suppressLayout.

To freeze:

recyclerView.suppressLayout(true)

To unfreeze:

recyclerView.suppressLayout(false)
Shailendra Madda
  • 20,649
  • 15
  • 100
  • 138
16
recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
        @Override
        public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
            // Stop only scrolling.
            return rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING;
        }
    });

ypresto
  • 975
  • 1
  • 13
  • 23
rajesh
  • 161
  • 1
  • 2
16

You can disable scrolling by freezing your RecyclerView.

To freeze: recyclerView.setLayoutFrozen(true)

To unfreeze: recyclerView.setLayoutFrozen(false)

Virat Singh
  • 1,464
  • 1
  • 12
  • 16
15

There is a simple answer.

LinearLayoutManager lm = new LinearLayoutManager(getContext()) {
                @Override
                public boolean canScrollVertically() {
                    return false;
                }
            };

The above code disables RecyclerView's verticall scrolling.

Emad Razavi
  • 1,903
  • 2
  • 17
  • 24
14

Create class which extend RecyclerView class

public class NonScrollRecyclerView extends RecyclerView {

    public NonScrollRecyclerView(Context context) {
        super(context);
    }

    public NonScrollRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public NonScrollRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    }
}

This will disable the scroll event, but not the click events

Use this in your XML do the following:

  <com.yourpackage.xyx.NonScrollRecyclerView 
     ...
     ... 
  />
Community
  • 1
  • 1
Ashish
  • 873
  • 10
  • 20
  • Thanks! This all is needed when we want to allow recycler view to take full height according to contents without internal scrolling. :) – Rahul Rastogi Mar 21 '18 at 05:01
  • But if this recycler view is in a scrolling view (e.g.ScrollView) then the layout manager should override canScrollVertically() method returning false from it. – Rahul Rastogi Mar 21 '18 at 05:13
  • @RahulRastogi use NestedScrollView instead of ScrollView – Ashish Mar 21 '18 at 09:19
  • Hey @AshishMangave , Please tell how to enable it again programmatically – Shruti Apr 20 '18 at 05:50
  • @Shruti we can’t do this programatically. bcz we directly override recyclerview ’s onMeasure method.you can try for this recyclerView.setNestedScrollingEnabled(false) .this will help you – Ashish Apr 20 '18 at 06:13
  • @Ashish, This is for stop vertical scroll, please tell me how to stop horizontal scroll – Shruti Apr 20 '18 at 06:29
13

If you just disable only scroll functionality of RecyclerView then you can use setLayoutFrozen(true); method of RecyclerView. But it can not be disable touch event.

your_recyclerView.setLayoutFrozen(true);
Ekta Bhawsar
  • 746
  • 11
  • 26
13

In Kotlin, if you don't want to create an extra class just for setting one value, you can create anonymous class from LayoutManager:

recyclerView.layoutManager = object : LinearLayoutManager(context) {
    override fun canScrollVertically(): Boolean = false
}
Micer
  • 8,731
  • 3
  • 79
  • 73
12

Wrote a kotlin version:

class NoScrollLinearLayoutManager(context: Context?) : LinearLayoutManager(context) {
    private var scrollable = true

    fun enableScrolling() {
        scrollable = true
    }

    fun disableScrolling() {
        scrollable = false
    }

    override fun canScrollVertically() =
            super.canScrollVertically() && scrollable


    override fun canScrollHorizontally() =
            super.canScrollVertically()

 && scrollable
}

usage:

recyclerView.layoutManager = NoScrollLinearLayoutManager(context)
(recyclerView.layoutManager as NoScrollLinearLayoutManager).disableScrolling()
I'm a frog dragon
  • 7,865
  • 7
  • 46
  • 49
7

in XML :-

You can add

android:nestedScrollingEnabled="false"

in the child RecyclerView layout XML file

or

in Java :-

childRecyclerView.setNestedScrollingEnabled(false);

to your RecyclerView in Java code.

Using ViewCompat (Java) :-

childRecyclerView.setNestedScrollingEnabled(false); will work only in android_version>21 devices. to work in all devices use the following

ViewCompat.setNestedScrollingEnabled(childRecyclerView, false);

jafarbtech
  • 6,842
  • 1
  • 36
  • 55
6

Another alternative is setLayoutFrozen, but it comes with a bunch of other side effects.

https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html#setLayoutFrozen(boolean)

Taig
  • 6,718
  • 4
  • 44
  • 65
5

Extend the LayoutManager and override canScrollHorizontally()and canScrollVertically() to disable scrolling.

Be aware that inserting items at the beginning will not automatically scroll back to the beginning, to get around this do something like:

  private void clampRecyclerViewScroll(final RecyclerView recyclerView)
  {
    recyclerView.getAdapter().registerAdapterDataObserver(new RecyclerView.AdapterDataObserver()
    {
      @Override
      public void onItemRangeInserted(int positionStart, int itemCount)
      {
        super.onItemRangeInserted(positionStart, itemCount);
        // maintain scroll position at top
        if (positionStart == 0)
        {
          RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
          if (layoutManager instanceof GridLayoutManager)
          {
            ((GridLayoutManager) layoutManager).scrollToPositionWithOffset(0, 0);
          }else if(layoutManager instanceof LinearLayoutManager)
          {
            ((LinearLayoutManager) layoutManager).scrollToPositionWithOffset(0, 0);
          }
        }
      }
    });
  }
Aidanvii
  • 580
  • 5
  • 6
5

I know this already has an accepted answer, but the solution doesn't take into account a use-case that I came across.

I specifically needed a header item that was still clickable, yet disabled the scrolling mechanism of the RecyclerView. This can be accomplished with the following code:

recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
                            @Override
     public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
         return e.getAction() == MotionEvent.ACTION_MOVE;
     }

     @Override
     public void onTouchEvent(RecyclerView rv, MotionEvent e) {

     }

     @Override
     public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
});
Karthikeyan
  • 196
  • 2
  • 10
Ryan Simon
  • 345
  • 2
  • 13
  • For some reason, you have to click just right, without moving for this to work. – Jared Burrows Jan 09 '16 at 21:35
  • Good point, @JaredBurrows. This is because we're disregarding ACTION_MOVE. For touch to feel natural, there's some give between touching, and slight movement on the screen. Unfortunately, I wasn't able to solve for that problem. – Ryan Simon Jan 15 '16 at 22:23
  • Thanks, exactly what I needed! – stavros.3p Dec 13 '19 at 23:42
3

For some reason @Alejandro Gracia answer starts working only after a few second. I found a solution that blocks the RecyclerView instantaneously:

recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
            @Override
            public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
                return true;
            }
            @Override
            public void onTouchEvent(RecyclerView rv, MotionEvent e) {
            }
            @Override
            public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
            }
        });
vovahost
  • 34,185
  • 17
  • 113
  • 116
3

Override onTouchEvent() and onInterceptTouchEvent() and return false if you don't need OnItemTouchListener at all. This does not disable OnClickListeners of ViewHolders.

public class ScrollDisabledRecyclerView extends RecyclerView {
    public ScrollDisabledRecyclerView(Context context) {
        super(context);
    }

    public ScrollDisabledRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public ScrollDisabledRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        return false;
    }
}
ypresto
  • 975
  • 1
  • 13
  • 23
3

Just add this to your recycleview in xml

 android:nestedScrollingEnabled="false"

like this

<android.support.v7.widget.RecyclerView
                    android:background="#ffffff"
                    android:id="@+id/myrecycle"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:nestedScrollingEnabled="false">
anas
  • 133
  • 2
  • 4
3

Add

android:descendantFocusability="blocksDescendants"

in your child of SrollView or NestedScrollView (and parent of ListView, recyclerview and gridview any one)

Pankaj Talaviya
  • 3,328
  • 28
  • 31
3

You should just add this line:

recyclerView.suppressLayout(true)
Majid Sadeghi
  • 180
  • 11
  • Tells the RecyclerView to suppress all layout and scroll calls until layout suppression is disabled. [refer to docs](https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/RecyclerView#suppresslayout) – Ruan_Lopes Aug 20 '20 at 19:21
2

I have been struggling in this issue for some hour, So I would like to share my experience, For the layoutManager solution it is fine but if u want to reEnable scrolling the recycler will back to top.

The best solution so far (for me at least) is using @Zsolt Safrany methode but adding getter and setter so you don't have to remove or add the OnItemTouchListener.

As follow

public class RecyclerViewDisabler implements RecyclerView.OnItemTouchListener {

    boolean isEnable = true;

    public RecyclerViewDisabler(boolean isEnable) {
        this.isEnable = isEnable;
    }

    public boolean isEnable() {
        return isEnable;
    }

    public void setEnable(boolean enable) {
        isEnable = enable;
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        return !isEnable;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {}

   @Override
   public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept){}
 }

Usage

RecyclerViewDisabler disabler = new RecyclerViewDisabler(true);
feedsRecycler.addOnItemTouchListener(disabler);

// TO ENABLE/DISABLE JUST USE THIS
disabler.setEnable(enable);
Aladdin
  • 61
  • 6
2

There is a more straightforward way to disable scrolling (technically it is more rather interception of a scrolling event and ending it when a condition is met), using just standard functionality. RecyclerView has the method called addOnScrollListener(OnScrollListener listener), and using just this you can stop it from scrolling, just so:

recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
        if (viewModel.isItemSelected) {
            recyclerView.stopScroll();
        }
    }
});

Use case: Let's say that you want to disable scrolling when you click on one of the items within RecyclerView so you could perform some actions with it, without being distracted by accidentally scrolling to another item, and when you are done with it, just click on the item again to enable scrolling. For that, you would want to attach OnClickListener to every item within RecyclerView, so when you click on an item, it would toggle isItemSelected from false to true. This way when you try to scroll, RecyclerView will automatically call method onScrollStateChanged and since isItemSelected set to true, it will stop immediately, before RecyclerView got the chance, well... to scroll.

Note: for better usability, try to use GestureListener instead of OnClickListener to prevent accidental clicks.

Tim Jorjev
  • 89
  • 1
  • 2
  • 5
  • `stopScroll()` is not to freeze the scroll, it's just to halt/stop scrolling recyclerview. – Farid May 31 '19 at 06:21
  • @FARID, yes, this method just stops any scroll in progress, and in this particular case, it does that every time when a user tries to scroll RecyclerView content with `isItemSelected` set to `true`. Otherwise, you would need a custom RecyclerView to disable scrolling for good and I wanted to avoid it since I needed just a little extra functionality, which this solution provides. – Tim Jorjev Jun 02 '19 at 00:02
2

You can add this line after setting your adapter

ViewCompat.setNestedScrollingEnabled(recyclerView, false);

Now your recyclerview will work with smooth scrolling

2

For whom want's to just prevent the user to scroll the RecyclerView, without loose the smoothScrollToPosition or any other "go to position" method, I'd recommend rather extending the RecyclerView class, overriding the onTouchEvent. Like this:

            public class HardwareButtonsRecyclerView extends RecyclerView {
            
                    public HardwareButtonsRecyclerView(@NonNull Context context) {
                        super(context);
                    }
            
                    public HardwareButtonsRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
                        super(context, attrs);
                    }
            
                    public HardwareButtonsRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
                        super(context, attrs, defStyleAttr);
                    }
            
                @Override
                public boolean onTouchEvent(MotionEvent e) {
                    return false;
                }
            }
Natan Lotério
  • 689
  • 1
  • 10
  • 20
2

At activity's onCreate method, you can simply do:

recyclerView.stopScroll()

and it stops scrolling.

Hasim D
  • 112
  • 3
1

Here is how I did it with data binding:

            <android.support.v7.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:clipChildren="false"
                android:onTouch="@{(v,e) -> true}"/>

In place of the "true" I used a boolean variable that changed based on a condition so that the recycler view would switch between being disabled and enabled.

bwhite
  • 2,643
  • 1
  • 18
  • 8
1

Came across with a fragment that contains multiple RecycleView so I only need one scrollbar instead of one scrollbar in each RecycleView.

So I just put the ScrollView in the parent container that contains the 2 RecycleViews and use android:isScrollContainer="false" in the RecycleView

<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutManager="LinearLayoutManager"
    android:isScrollContainer="false" />
pk028382
  • 95
  • 1
  • 10
1

For stop scrolling by touch but keep scrolling via commands :

if (appTopBarMessagesRV == null) { appTopBarMessagesRV = findViewById(R.id.mainBarScrollMessagesRV);

        appTopBarMessagesRV.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener() {
            @Override
            public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {

                if ( rv.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING)
                {
                     // Stop  scrolling by touch

                    return false;
                }
                return  true;
            }
        });
    }
Guy
  • 133
  • 2
  • 11
1

You can creat a Non Scrollable Recycler View which extends a Recycler View class, as follows:

import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;

import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;

public class NonScrollRecyclerView extends RecyclerView {

    public NonScrollRecyclerView(Context context) {
        super(context);
    }

    public NonScrollRecyclerView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public NonScrollRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasure, int heightMeasure) {
        int heightMeasureCustom = MeasureSpec.makeMeasureSpec(
                Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
        super.onMeasure(widthMeasure, heightMeasureCustom);
        ViewGroup.LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    }
}
Kishan Viramgama
  • 893
  • 1
  • 11
  • 23
Aman Garg
  • 131
  • 2
  • 2
0

MAY 2022

This way worked for me after a lot of tries in new versions of android and APIs.

The New Answer With Kotlin

  1. create a class called ScrollDisabledRecyclerView and put codes like this:

class ScrollDisabledRecyclerView : RecyclerView {

constructor(context: Context?) : super(context!!)
constructor(context: Context?, @Nullable attrs: AttributeSet?) : super(context!!, attrs)
constructor(context: Context?, @Nullable attrs: AttributeSet?, defStyle: Int) : super(
    context!!,
    attrs,
    defStyle
)

override fun onTouchEvent(e: MotionEvent): Boolean {
    return e.action == MotionEvent.ACTION_MOVE
}

override fun onInterceptTouchEvent(e: MotionEvent): Boolean {
    return false
}  }
  1. use this class in your XML instead of RecyclerView (this class is extended from it):
 <info.sanaebadi.ScrollDisabledRecyclerView

        android:id="@+id/recyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:clipToPadding="true"
        tools:listitem="@layout/multiple_questions_row" />
  1. and at last, handle the next and previous with buttons in MainActiviy like this:

note: I AM USING ViewBinding

binding.buttonNextQuestion.setOnClickListener {
            val totalItemCount: Int = binding.recyclerView.adapter!!.itemCount
            if (totalItemCount <= 0) return@setOnClickListener
            val lastVisibleItemIndex: Int = linearLayoutManager.findLastVisibleItemPosition()
            if (lastVisibleItemIndex >= totalItemCount) return@setOnClickListener
            linearLayoutManager.smoothScrollToPosition(
                binding.recyclerView,
                null,
                lastVisibleItemIndex + 1
            )

        }
        binding.buttonPreviousQuestion.setOnClickListener {
            val firstVisibleItemIndex: Int =
                linearLayoutManager.findFirstCompletelyVisibleItemPosition()
            if (firstVisibleItemIndex > 0) {
                linearLayoutManager.smoothScrollToPosition(
                    binding.recyclerView,
                    null,
                    firstVisibleItemIndex - 1
                )
            }
        }
Sana Ebadi
  • 6,656
  • 2
  • 44
  • 44
0

Now the set recyclerView.setLayoutFrozen(true); // for disabling scrolling of recycler view is deprecated use recyclerView.suppressLayout(true)