Parar a rolagem do pai (NestedScrollview) Ao rolar o Filho (RecyclerView)

8

Preciso de um comportamento semelhante a esta implementação. Mas NestedScrollView seria o pai e RecyclerView seria o filho de seria NestedScrollView.

Por exemplo: https://medium.com/widgetlabs-engineering/scrollable-nestedscrollviews-inside-recyclerview-ca65050d828a

Não tenho certeza se isso pode ser alcançado. Tentei desativar o pai (NSV) enquanto o filho (RV) está rolando Mas a rolagem no filho rola a exibição inteira, incluindo o pai.

Rockin
fonte
você conseguiu a resposta como por meio pode realizáveis, por favor você pode compartilhar algum código
Damodhar

Respostas:

2

Eu implementei a solução Marc Knaup e todas as obras correm o evento se NestedScrollViewseria o pai e o resultado foi mostrado abaixo

insira a descrição da imagem aqui

btw, eu coloquei o que eu fiz

CustomRecycleView

package com.example.nested_scroll_test;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import androidx.core.view.NestedScrollingParent;
import androidx.recyclerview.widget.RecyclerView;

public class CustomRecycleView extends RecyclerView implements NestedScrollingParent {
    private View nestedScrollTarget = null;
    private boolean nestedScrollTargetIsBeingDragged = false;
    private boolean nestedScrollTargetWasUnableToScroll = false;
    private boolean skipsTouchInterception = false;


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

    public CustomRecycleView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomRecycleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean temporarilySkipsInterception = nestedScrollTarget != null;
        if (temporarilySkipsInterception) {
            // If a descendent view is scrolling we set a flag to temporarily skip our onInterceptTouchEvent implementation
            skipsTouchInterception = true;
        }

        // First dispatch, potentially skipping our onInterceptTouchEvent
        boolean handled = super.dispatchTouchEvent(ev);

        if (temporarilySkipsInterception) {
            skipsTouchInterception = false;

            // If the first dispatch yielded no result or we noticed that the descendent view is unable to scroll in the
            // direction the user is scrolling, we dispatch once more but without skipping our onInterceptTouchEvent.
            // Note that RecyclerView automatically cancels active touches of all its descendents once it starts scrolling
            // so we don't have to do that.
            if (!handled || nestedScrollTargetWasUnableToScroll) {
                handled = super.dispatchTouchEvent(ev);
            }
        }

        return handled;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        return !skipsTouchInterception && super.onInterceptTouchEvent(e);
    }

    @Override
    public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        if (dyConsumed != 0) {
            // The descendent was actually scrolled, so we won't bother it any longer.
            // It will receive all future events until it finished scrolling.
            nestedScrollTargetIsBeingDragged = true;
            nestedScrollTargetWasUnableToScroll = false;
        } else if (dyConsumed == 0 && dyUnconsumed != 0) {
            // The descendent tried scrolling in response to touch movements but was not able to do so.
            // We remember that in order to allow RecyclerView to take over scrolling.
            nestedScrollTargetWasUnableToScroll = true;
            if (target.getParent() != null)
                target.getParent().requestDisallowInterceptTouchEvent(false);
        }
    }

    @Override
    public void onNestedScrollAccepted(View child, View target, int axes) {
        if (axes != 0 && View.SCROLL_AXIS_VERTICAL != 0) {
            // A descendent started scrolling, so we'll observe it.
            nestedScrollTarget = target;
            nestedScrollTargetIsBeingDragged = false;
            nestedScrollTargetWasUnableToScroll = false;
        }

        super.onNestedScrollAccepted(child, target, axes);
    }

    @Override
    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
        return nestedScrollAxes != 0 && View.SCROLL_AXIS_VERTICAL != 0;
    }

    @Override
    public void onStopNestedScroll(View child) {
        nestedScrollTarget = null;
        nestedScrollTargetIsBeingDragged = false;
        nestedScrollTargetWasUnableToScroll = false;
    }
}

content_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">


    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="150dp"
                android:background="#FFFFFF"
                android:orientation="vertical">
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:textAlignment="center"
                    android:text="Top Section"/>
            </LinearLayout>

            <com.example.nested_scroll_test.CustomRecycleView
                android:id="@+id/rw"
                android:layout_width="match_parent"
                android:layout_height="300dp"
                android:background="@color/colorPrimary"
                android:nestedScrollingEnabled="true"
                android:orientation="vertical">

            </com.example.nested_scroll_test.CustomRecycleView>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="150dp"
                android:background="#FFFFFF"
                android:orientation="vertical" >
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:textAlignment="center"
                    android:text="Bottom Section"/>
            </LinearLayout>
        </LinearLayout>
    </androidx.core.widget.NestedScrollView>


</androidx.coordinatorlayout.widget.CoordinatorLayout>

RecycleViewItem.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/nsw"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="2dp"
        android:background="#CCCC"
        android:gravity="center"
        android:nestedScrollingEnabled="false"
        android:orientation="vertical"
        android:padding="2dp"
        android:textColor="#FFFFFF" />
</androidx.core.widget.NestedScrollView>
Mr.AF
fonte
0

@Rockin use overscrollmode bro :)

 <androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:fillViewport="true"
    android:overScrollMode="always"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/color_white"
        android:orientation="vertical">


       <androidx.recyclerview.widget.RecyclerView                
           android:id="@+id/activity_insight_recyclerview_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="@dimen/_20sdp"
          app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            tools:listitem="@layout/raw_insight" />
Parth Pitroda
fonte
o comportamento de rolagem mencionado neste meio.com/widgetlabs-engineering/… não pode ser alcançado usando o modo de rolagem excessiva.
Rockin
@ Rockin você tem que dar android: layout_height = "match_parent" e é desafiadoramente trabalho que eu estou usando isso no meu código.
Parth Pitroda
0

poste tudo o que você tentou até agora.

seu xml deve ser,

<android.support.v4.widget.NestedScrollView
            android:id="@+id/nestedScrollView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:overScrollMode="never">


            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical">

              <View > <!-- upper content -->

              <!-- set recycler view with with wrap_content -->
              <android.support.v7.widget.RecyclerView
                    android:id="@+id/recyclerView"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />

            </LinearLayout>
      </android.support.v4.widget.NestedScrollView>

defina o comportamento de rolagem dentro do método onCreateView () / onCreate (). requer Api 21+.

    RecyclerView v = (RecyclerView) findViewById(...);
    v.setNestedScrollingEnabled(false);
                   or 
    android:nestedScrollingEnabled="false"  // inside recycler view in xml file
Radhey
fonte
o comportamento de rolagem mencionado neste meio.com/widgetlabs-engineering/… não pode ser alcançado usando o modo de rolagem excessiva.
Rockin
isso não é uma solução porque o android: nestedScrollingEnabled = "false" congela a reciclagem.
Mr.AF
0

Esta é uma demonstração do que você deseja procurar, no arquivo MainActivity.xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="MainActivity">

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:focusableInTouchMode="true"
            android:orientation="vertical">
            <ImageView
                android:id="@+id/top_seller"
                android:layout_width="match_parent"
                android:layout_height="200sp"
                android:background="@color/colorAccent"
                android:contentDescription="@string/app_name"
                android:adjustViewBounds="true"
                android:src="@drawable/background"
                android:scaleType="fitXY"/>
            <ImageView
                android:id="@+id/top_seller1"
                android:layout_width="match_parent"
                android:layout_height="200sp"
                android:background="@color/colorAccent"
                android:contentDescription="@string/app_name"
                android:adjustViewBounds="true"
                android:src="@drawable/background"
                android:scaleType="fitXY"/>
            <android.support.v7.widget.RecyclerView
                android:id="@+id/product_list"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:scrollbars="none" />
            <ImageView
                android:id="@+id/top_seller2"
                android:layout_width="match_parent"
                android:layout_height="200sp"
                android:background="@color/colorAccent"
                android:contentDescription="@string/app_name"
                android:adjustViewBounds="true"
                android:src="@drawable/background"
                android:scaleType="fitXY"/>
            <ImageView
                android:id="@+id/top_seller3"
                android:layout_width="match_parent"
                android:layout_height="200sp"
                android:background="@color/colorAccent"
                android:contentDescription="@string/app_name"
                android:adjustViewBounds="true"
                android:src="@drawable/background"
                android:scaleType="fitXY"/>
        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>
</LinearLayout>

No seu método de classe MainActivity.javaonCreate :

   RecyclerView bestRecyclerView = findViewById(R.id.product_list);
   GridLayoutManager mGrid = new GridLayoutManager(this, 2);
   bestRecyclerView.setLayoutManager(mGrid);
   bestRecyclerView.setHasFixedSize(true);
   bestRecyclerView.setNestedScrollingEnabled(false);
   // Create ProductAdapter for  RecyclerView data
   ProductAdapter mAdapter = new ProductAdapter(MainActivity4.this,getProductTestData());
   bestRecyclerView.setAdapter(mAdapter);

insira a descrição da imagem aqui

Espero que ajude você ...!

Viral Patel
fonte
Você encontrou suas respostas ou precisa de ajuda?
Viral Patel
Isso é útil para você?
Viral Patel
-1

Você tentou subclassificar o RV e substituir onInterceptTouchEvent?

override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {

    when (event!!.action and MotionEvent.ACTION_MASK) {


        MotionEvent.ACTION_DOWN -> {

            // WE INTERACT WITH THIS RV. PREVENT PARENT TO INTERCEPT 
            parent.requestDisallowInterceptTouchEvent(true) 

        }


        MotionEvent.ACTION_MOVE, MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {

            // THIS SEEMS LIKE IT WILL HAVE "DEFAULT" BEHAVIOUR BUT SINCE WE CURRENTLY DRAGGING THE RV THEN IT WONT SCROLL THE PARENT  
            parent.requestDisallowInterceptTouchEvent(false)

        }

    }

    return false
}
nfl-x
fonte