27

Is it possible to make a RecyclerView not clickable? I want this because my RecyclerView just shows some small icons, within a clickable CardView. So if someone taps the icons, it should just click (and animate) the parent CardView instead.

I have tried the following:

  1. recyclerView.setClickable(false);
  2. recyclerView.setFocusable(false);
  3. Extend RecyclerView and make onTouchEvent(MotionEvent) return false.
  4. Use method 3 above and use itemView.setClickable(false); in the RecyclerView Adapter. This works, the click is sent to the parent. However, now the RecyclerView is not scrollable anymore.
  5. Set clickable="false", focusable="false", focusableInTouchMode="false" in inflated list item XML. (See comment @Ibrahim)
  6. Call recyclerView#setLayoutFrozen(true) and itemView.setClickable(false);. This works, but has the same issue as #4.

Any ideas how to disable and pass through the click events of the RecyclerView to the parent view? Note that the RecyclerView still needs to be scrollable (horizontal).


EDIT:
User @c.dunlap suggested to set OnClick listeners to the icons, and just "redirect" the click to the parent's click action. This would work, but there won't be a click animation on the parent view. And if someone clicks outside an itemView - but still inside the RecyclerView (e.g. ItemDecoration padding) - the click is not detected. So unfortunately this is not a solution.

Thomas Vos
  • 12,271
  • 5
  • 33
  • 71
  • What is code for adapter? – Vlado Pandžić Jul 24 '17 at 20:12
  • @VladoPandžić The adapter really doesn't have anything special. It inflates the layout as normal. The only code within `onBindViewHolder(...)` is setting a Drawable to the `ImageView`. – Thomas Vos Jul 24 '17 at 20:19
  • 1
    did you tried to set `clickable` ,`focusable` and focusableontouchmode false in inflated layout xml? –  Jul 24 '17 at 20:38
  • @Ibrahim Just tried, didn't make a difference. – Thomas Vos Jul 24 '17 at 20:42
  • Also try **clickable="false"**, **focusable="false"**, **focusableInTouchMode="false**" on recycle **xml** , and provide the recycle view click implementaion if avilable –  Jul 24 '17 at 20:47
  • @Ibrahim Did you read my question? See item 1 and 2. Could you explain what a RecyclerView click implementation is? – Thomas Vos Jul 24 '17 at 20:48
  • Can you share your codes so we can reproduce your problem? – Felipe Castilhos Jul 24 '17 at 20:54
  • @FelipeCastilhos You can try it for yourself. It is really easy. Just put a `RecyclerView` inside a clickable `CardView`. – Thomas Vos Jul 24 '17 at 20:59
  • If you capture the touchEvent it will block the scroll, even if you embed your listview in wrap_content into a scrollview (Yeah I tried for science). I haven't any solution for now. I have created a repo to try this. https://github.com/vdubedout/non-clickable-recyclerview – Vincent D. Sep 14 '17 at 20:56
  • @ThomasVos were you ever able to find a solution for this one? Running into the same issue myself. Thanks! – ElectronAnt Oct 09 '18 at 20:11
  • @Aneem I didn't find a solution yet, but I haven't looked at this issue in the past few months. In my project, a non scrolling list is good enough for now. However, if you find a solution, please share it! – Thomas Vos Oct 11 '18 at 18:02

3 Answers3

18

You should extend the parent View and intercept the click, so the recyclerview doesn't receive it.

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    return true;
}

Credits to: Solution

nsL
  • 3,722
  • 3
  • 23
  • 40
3

My preferred way of handling things like this is to attach a listener from your adapter that will be called when each icon in your recycler view is clicked. Then your activity can respond in the appropriate way. For instance:

public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private MyAdapterListener mListener;

    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
         holder.itemView.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 mListener.iconClicked();
             }
         });
    }

    public void setListener(MyAdapterListener listener) {
        mListener = listener;
    }

    public interface MyAdapterListener {
        void iconClicked();
    }

}

Then in your activity, you can simply create an instance of MyAdapterListener and set it as the listener for your Recycler View's adapter. Then when iconClicked() function is triggered, execute the code that would be executed on parent click.

c.dunlap
  • 600
  • 1
  • 11
  • 28
  • 2
    Thanks for your answer. This would work but there won't be a click animation on the parent view. Also, what if someone clicks outside an `itemView`? How should I handle the click? – Thomas Vos Jul 25 '17 at 07:52
  • Please see the EDIT part of my question. – Thomas Vos Jul 26 '17 at 13:13
  • If you modify your itemViews so that they do not have any spacing between them in the recycler view, but instead having padding inside of the itemView, then your itemViews will fill the recyclerView making it impossible to click on the recyclerView but not an item view. If you are doing something else that makes this unfeasible, you will likely need to share your layouts so that we can help you further. Personally, I find that this method typically leads to nicer layouts as well (even spacing between cells). – c.dunlap Jul 26 '17 at 19:45
  • 1
    The problem is not that there is space in-between the itemViews. Like you said, I can work around that by using padding within the itemView layouts. The problem is that if there are just a few "icons", then not the whole RecyclerView is used, and there is still space left. I can't set the RecyclerView to wrap_content because it needs to be in-between two other views. So I don't think your answer will work for my situation. Any ideas for other solutions? – Thomas Vos Jul 26 '17 at 19:51
  • Can you share your layout? – c.dunlap Jul 27 '17 at 20:07
  • This won't allow clicking effect on the parent of the RecyclerView. – android developer Sep 24 '19 at 11:19
-2

I had same issue, after i trying much more things, i used one more layout over recyclerview.

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.v7.widget.RecyclerView
        android:layoutwidth="match_parent"
        android:layout_height="match_parent">
    </android.support.v7.widget.RecyclerView>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

after that you can visible and gone that "LinearLayout". This works 100%.

  • 1
    How does this work? Could you explain how this solves the question? – Thomas Vos Jul 24 '17 at 20:50
  • When you want make recyclerview desable, you can make visible that LinearLayout, when the LinearLayout will viaible the recyclerview will not work, after that you can gone that LinearLayout for make recyclerview enable. – Deepak Tiwari Jul 26 '17 at 12:27
  • Ok, I understand, but that wasn't my question. My question was how to disable the `RecyclerView` **and** pass clicks to the parent view. I also noted the `RecyclerView` still needs to be scrollable. If I just wanted to disable the `RecyclerView` I could use `setEnabled(false)` on both the `RecyclerView` and the `itemView`s, but then the click won't be passed to the parent layout. – Thomas Vos Jul 26 '17 at 12:29
  • can you upload your xml, i"ll give proper ans. – Deepak Tiwari Aug 24 '17 at 18:47
  • @ThomasVos it works because the LinearLayout masks the whole recyclerview, and receives the clicks instead. – Brill Pappin Nov 05 '20 at 12:59