0

I am using a RecyclerView inside a RecyclerView. I want to be able to scroll through both. Therefore I included this answer to my child RecyclerView, which worked... kind of. I can scroll the child, but when I stop scrolling and want to scroll the child again, I have to tap on the parent first before being able to scroll the child or the parent again. See the video. Also interesting is the fact that the parent is moved immediately like in the video. I usually have to long-press to move an item. And when I raise my finger to stop scrolling the child but continue scrolling immediately, I can scroll the child without touching the parent first. But I have to continue very fast (before the tap animation is finished). I am very confused about this behavior. Can someone fix this?

the problem

I tried to set requestDisallowInterceptTouchEvent to false too, but it didn't fix the problem.

RecyclerView.OnItemTouchListener scrollTouchListener = new RecyclerView.OnItemTouchListener() {
        @Override
        public boolean onInterceptTouchEvent(@NonNull RecyclerView recyclerView, MotionEvent e) {
            int action = e.getAction();
            Log.d("Output> ", "" + action);
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    recyclerView.getParent().requestDisallowInterceptTouchEvent(true);
                    break;
                case MotionEvent.ACTION_CANCEL:
                case MotionEvent.ACTION_UP:
                    recyclerView.getParent().requestDisallowInterceptTouchEvent(false);
                    break;
            }
            return false;
        }

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

        }

        @Override
        public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

        }
    };

Edit

With the help of @Zain, I managed to get rid of my RecyclerView.OnItemTouchListener above. But my current situation is still buggy, as you see in the GIF below. In the beginning, I was scrolling very fast - it worked. Then I scrolled through with long breaks - worked. But when I scroll through with medium speed, you can see what happens. The parent recycler view is moving instead of scrolling the child recycler view.
the buggy scrolling problem

I am sure that I am missing something — That's why I want to provide more of my current code.

My parent recycler view touch listener. (Code taken from @Zain)

recyclerViewParent.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                ViewGroup touchedView = (ViewGroup) recyclerViewParent.findChildViewUnder(event.getX(), event.getY());
                if (touchedView != null) {
                    Log.d("parent>", touchedView.toString());
                    for (int i = 0; i < touchedView.getChildCount(); i++) {
                        if (touchedView.getChildAt(i) instanceof RecyclerView) {
                            if (BiotopesFragment.this.isViewInBounds(touchedView, (int) event.getX(), (int) event.getY())) {
                                touchedView.onTouchEvent(event);
                                return true;
                            }
                        }
                    }
                }

                return false;
            }
        });

private boolean isViewInBounds(View view, int x, int y) {
        Rect outRect = new Rect();
        int[] location = new int[2];
        view.getDrawingRect(outRect);
        view.getLocationOnScreen(location);
        outRect.offset(location[0], location[1]);
        return outRect.contains(x, y);
    }

In my parents RecyclerView Adapter, I set a touch listener for my child recyclerView

holder.recyclerViewChild.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent e) {
                    //this will disallow the touch request for parent scroll on touch of child view
                    Log.d("child> ", "" + view.toString());
                    view.getParent().getParent().getParent().requestDisallowInterceptTouchEvent(true);
                    return false;
                }
            });

My parent recycler view inside a fragment

<androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerViewParent"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textViewFreshwater" />

This is my list item used by the parent recycler view

<com.google.android.material.card.MaterialCardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="280dp"
    android:layout_height="156dp"
    android:layout_margin="8dp"
    android:clickable="true"
    android:focusable="true"
    app:layout_flexGrow="1"
    app:cardCornerRadius="20dp"
    style="?attr/materialCardViewFilledStyle">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.imageview.ShapeableImageView
            android:id="@+id/imageViewBiotopeCardview"
            android:background="@drawable/shadow"
            android:layout_width="130dp"
            android:layout_height="130dp"
            android:layout_marginTop="-20dp"
            android:layout_marginEnd="-20dp"
            android:contentDescription="@string/imageViewDescription_biotope_image"
            android:scaleType="centerCrop"
            android:cropToPadding="true"
            android:padding="5dp"
            android:elevation="5dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:strokeWidth="5dp"
            app:strokeColor="@color/black"
            app:shapeAppearanceOverlay="@style/Theme.WaterTestTimer.CircleCorners" />

        <TextView
            android:id="@+id/textViewBiotopeTitle"
            android:layout_width="170dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="0dp"
            android:layout_marginTop="8dp"
            android:text=""
            android:textStyle="bold"
            android:singleLine="true"
            android:ellipsize="middle"
            android:textSize="20sp"
            android:textAlignment="center"
            app:layout_constraintEnd_toStartOf="@+id/imageViewBiotopeCardview"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <com.google.android.material.divider.MaterialDivider
            android:id="@+id/biotope_divider"
            app:dividerColor="?attr/customDividerColor"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginHorizontal="10dp"
            app:layout_constraintEnd_toStartOf="@+id/imageViewBiotopeCardview"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/textViewBiotopeTitle" />

        <TextView
            android:id="@+id/textViewLastValuesDate"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:text="@string/biotopeCardView_lastValues"
            android:textAlignment="center"
            android:textSize="14sp"
            app:layout_constraintEnd_toStartOf="@+id/imageViewBiotopeCardview"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/biotope_divider" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recyclerViewChild"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:paddingHorizontal="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/imageViewBiotopeCardview" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>

And finally the list item of the child

<com.google.android.material.card.MaterialCardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:layout_margin="2dp"
    android:clickable="true"
    android:focusable="true"
    app:layout_flexGrow="1"
    app:cardCornerRadius="10dp"
    style="?attr/materialCardViewFilledStyle">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/backgroundTestValue"
        android:background="@color/potassium"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/textViewTestValueTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=""
            android:textSize="14sp"
            android:textColor="@color/white"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
Pezcraft
  • 270
  • 3
  • 15
  • Hopefully [this](https://stackoverflow.com/questions/68200773/vertical-recyclerview-nested-inside-vertical-recyclerview/68241775#68241775) could you help you out. – Zain May 27 '22 at 03:39
  • 1
    You need to intercept the touch event in the parent recyclerview, and when the coordinates of the touch are within the bounds of the child rv, you need to forward that touch event to it. Writing this on my phone, Ill try and give you some code soon. – Sean Blahovici May 27 '22 at 11:59
  • @Zain Thank you, but I need solutions for horizontal scrolling. – Pezcraft May 27 '22 at 17:17
  • Hey @Pezcraft it doesn't really matter in terms of your needs. What you actually need is to `return true` (to disable touch interception) on the touch event on the parent RV; but that requires to handle in the case that the child RV can intercept it; otherwise it should return false in order to allow the parent RV to scroll. I tried to do it somehow works; but it needs some refinement – Zain May 27 '22 at 17:25
  • @Zain Mine doesn't work. Can you provide me with your code? – Pezcraft May 27 '22 at 18:26
  • 1
    [HYG.. it's manipulated a bit](https://drive.google.com/file/d/1Fu9QgSzxJ8wby4z19raDmkcYXmnsTshI/view?usp=sharing) hopefully works... Just remove the test() method – Zain May 27 '22 at 20:02
  • @Zain I Still have problems, but I am sure I'm missing something. So I edited my post with my current code. – Pezcraft May 28 '22 at 00:46

0 Answers0