Dừng cuộn cha mẹ (NestedScrollview) Khi cuộn Con (RecyclerView)


8

Tôi cần hành vi tương tự như cách triển khai này Nhưng NestedScrollView sẽ là cha mẹ và RecyclerView sẽ là con của NestedScrollView.

Ví dụ: https://medium.com/widgetlabs-engineering/scrollable-nestedscrollview-inside-recyclerview-ca65050d828a

Tôi không chắc liệu nó có thể đạt được hay không. Đã vô hiệu hóa cha mẹ (NSV) trong khi con (RV) đang cuộn Nhưng cuộn trên con cuộn toàn bộ khung nhìn bao gồm cả bố mẹ.


bạn có nhận được câu trả lời theo phương tiện mà nó có thể đạt được không, bạn có thể vui lòng chia sẻ một số mã
Damodhar

Câu trả lời:


2

Tôi đã triển khai giải pháp Marc Knaup và tất cả các sự kiện đều hoạt động chính xác nếu NestedScrollViewlà phụ huynh và kết quả được hiển thị bên dưới

nhập mô tả hình ảnh ở đây

btw, tôi đặt những gì tôi đã làm

CustomRecyclView

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>

RecyclViewItem.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>

0

@Rockin sử dụng bro quá mức 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" />

hành vi cuộn được đề cập trong phương tiện này.com/widgetlabs-engineering/ không thể đạt được bằng cách sử dụng chế độ ghi đè.
Rockin

@Rockin bạn phải cung cấp cho android: layout_height = "match_parent" và nó hoạt động một cách chắc chắn tôi đang sử dụng mã này trong mã của mình.
Parth Pitroda

0

gửi toàn bộ những gì bạn đã cố gắng cho đến nay.

xml của bạn nên

<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>

thiết lập hành vi cuộn bên trong phương thức onCreateView () / onCreate (). yêu cầu Api 21+.

    RecyclerView v = (RecyclerView) findViewById(...);
    v.setNestedScrollingEnabled(false);
                   or 
    android:nestedScrollingEnabled="false"  // inside recycler view in xml file

hành vi cuộn được đề cập trong phương tiện này.com/widgetlabs-engineering/ không thể đạt được bằng cách sử dụng chế độ ghi đè.
Rockin

đây không phải là một giải pháp vì android: NestedScrollingEnables = "false" đóng băng tái chế.
Mr.AF

0

Đây là bản demo cho những gì bạn muốn, trong tệp 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>

Trong phương thức lớp MainActivity.java của bạn onCreate:

   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);

nhập mô tả hình ảnh ở đây

Tôi hy vọng nó sẽ giúp bạn ...!


Bạn đã tìm thấy câu trả lời của bạn hoặc cần một sự giúp đỡ?
Viral Patel

Nó có hữu ích cho bạn không?
Viral Patel

-1

Bạn đã thử phân lớp RV và ghi đè lênInterceptTouchEvent chưa?

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
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.