RecyclerView 嵌套 RecyclerView 无法滚动

15

一个Recycler View被嵌套在另一个Recycler View中,两者都需要竖向滚动。外部的Recycler View可以正常滚动,但是内部的Recycler View无法滚动。

以下是代码:

LinearLayoutManager mLayoutManager = new LinearLayoutManager(ViewActivity.this);
outerRecyclerView.setLayoutManager(mLayoutManager);
ViewAdapter adapter = new ViewAdapter(ViewActivity.this);
outerRecyclerView.setAdapter(adapter);

ViewAdapter如下所示:

public void onBindViewHolder(ViewAdapter.ViewViewHolder holder, int position)
{
  //RECYCLER VIEW
  //TODO: Inner Recycler view scroll movement
  LinearLayoutManager mLayoutManager = new LinearLayoutManager(context);
  holder.protocolRecyclerView.setLayoutManager(mLayoutManager);
  ViewProtocolAdapter adapter = new ViewProtocolAdapter(context);
  holder.protocolRecyclerView.setAdapter(adapter);
}

我已经在两个回收视图上尝试了以下内容,但无法解决问题

recyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
       @Override
       public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
           if(rv.getChildCount() > 0) {
               View childView = rv.findChildViewUnder(e.getX(), e.getY());
               if(childView ==listView) {
                   int action = e.getAction();
                   switch (action) {
                       case MotionEvent.ACTION_DOWN:
                           rv.requestDisallowInterceptTouchEvent(true);
                   }
               }
           }

           return false;
       }

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

       }

       @Override
       public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

       }
   });

也尝试了这个:

outerRecyclerView.setNestedScrollingEnabled(true);//Does not make any difference
innerRecyclerView.setNestedScrollingEnabled(true);//Recycler View start scrolling but very slowly and sometimes scrolls the outer one.

他们都需要垂直滚动吗?你期望什么样的行为? - cyroxis
你能否尝试为外部Recycler启用嵌套滚动并禁用内部滚动? - Moh'd Awad
拥有两个嵌套视图在同一方向上滚动是一个非常糟糕的想法。你为什么需要这样做呢? - Andrea Thacker
1
@DavidArgyleThacker实际上我在recycler view中有一种可扩展/可折叠的布局。当外部recycler view的行扩展时,它有另一个列表要显示,该列表属于该特定行。这就是为什么我有两个在同一方向滚动的recycler view。如果您有更好的实现方法,请告诉我。 - Nav
如果您想要一个可扩展的 Recycler View,可以尝试使用:https://github.com/thoughtbot/expandable-recycler-view - Harneev
10个回答

30
将以下ontouch监听器应用于内部recycler,该内部recycler可能在父级recycler的适配器中。
RecyclerView.OnItemTouchListener mScrollTouchListener = new RecyclerView.OnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
    int action = e.getAction();
    switch (action) {
        case MotionEvent.ACTION_MOVE:
            rv.getParent().requestDisallowInterceptTouchEvent(true);
            break;
    }
    return false;
}

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

}

@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

}
}; 

innerrecyclerView.addOnItemTouchListener(mScrollTouchListener);

这适用于 RecyclerView 中任何可以沿着相同方向滚动的视图类型。 - Emmanuel Guerra
这适用于RecyclerView内部的RecyclerView。谢谢。 - MohammadReza
1
但在这种情况下,我该如何添加onClick监听器,因为在这种情况下,点击监听器仅在2次点击中触发。 - Sattar
如果您想在已设置触摸监听器的回收站上单击,则可以通过此链接检测触摸监听器内的单击。 - Manthan Patel

5

我曾经在实现Recycler View时遇到了同样的问题。两个Recycler View都开始滚动,尽管嵌套Recycler View是一个不好的想法,但如果你想让它正常滚动,就必须禁用内部Recycler View的滚动。我不确定,但我认为是这个原因。如果行不通,请告诉我。如果不行,我会找到解决方案。

RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(parent.getContext()) {
            @Override
            public boolean canScrollVertically() {
                return false;
            }
        };

好的。我所做的方法是使内部的Recycler View无法滚动。因此,在滚动时,只有外部的Recycler View是活动的。这是其中一部分代码。 `RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(parent.getContext()) { @Override public boolean canScrollVertically() { return false; } }; innerRecyclerView.setLayoutManager(mLayoutManager);`现在,这段代码位于第一个Recycler View适配器(外部Recycler View)的**onCreateViewHolder()**中。 - mysticfyst

2

不要使用ScrollView,而是使用android.support.v4.widget.NestedScrollView

对我来说这很完美。

<android.support.v4.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:padding="4dp"
            />

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

0
现在,为了使其正常工作,您需要禁用子列表回收视图的垂直滚动。
LinearLayoutManager layoutManager = new LinearLayoutManager(context) {
            @Override
            public boolean canScrollVertically() {
                return false;
            }
    }; 

0

对于可能有用的人,我做了一些我在帖子周围看到的东西。

首先,我制作了一个自定义LinearLayoutManager,可以阻止垂直滚动。

    class CustomHorizontalLinearLayout(context: Context) :
LinearLayoutManager(context, RecyclerView.HORIZONTAL, false) {

override fun canScrollVertically(): Boolean {
    return false
}

然后将其设置为子RecyclerView(在这种情况下,它被称为recommendationRV):

itemView.recommendationRV?.apply {
                adapter = recyclerViewAdapter
                setRecycledViewPool(viewPool)
                setLayoutManager(layoutManager)
                setHasFixedSize(true)
            }

接下来,我在子RecyclerView的ViewHolder XML中添加了一个外部的NestedScrollView

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="220dp"
android:orientation="vertical"
android:background="@color/transparent"
android:paddingVertical="10dp">

<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recommendationRV"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/transparent"
        android:clickable="true"
        android:focusable="true"
        />
</androidx.core.widget.NestedScrollView>

这个方法似乎有效。虽然可能不是最佳方案,但对我来说非常管用,希望能帮到其他人。


0
parentScroll.setOnTouchListener(new View.OnTouchListener() {

    public boolean onTouch(View v, MotionEvent event) {

        findViewById(R.id.childScroll).getParent()
           .requestDisallowInterceptTouchEvent(false);

        return false;
     }
});

childScroll.setOnTouchListener(new View.OnTouchListener() {

      public boolean onTouch(View v, MotionEvent event) {  

           v.getParent().requestDisallowInterceptTouchEvent(true);
           return false;
      }
});

2
虽然这段代码可能解决了问题,但是包括解释它如何以及为什么解决了问题将有助于提高您的帖子质量,并可能导致更多的赞。请记住,您正在回答未来读者的问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加解释并指出适用的限制和假设。 - Suraj Rao

0

尝试使用这段代码,它对我有效。

<androidx.core.widget.NestedScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:isScrollContainer="true">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

 </androidx.core.widget.NestedScrollView>

-2

不要将一个Recycler View放在另一个Recycler View中,而应该膨胀内部的Recycler View。您可以拥有一个线性布局,并在Recycler View的onBindViewHolder中膨胀该布局。通过这样做,您将永远不会遇到滚动问题。


-2
你可以做的是,在第二个 RecyclerView 的视图持有者中作为根布局添加一个滚动视图。
  <ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/subContainer"
    >
    <android.support.v7.widget.RecyclerView
        android:id="@+id/subList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
         />
</ScrollView>

完成这些操作后,子列表回收视图可以充分利用wrap_content属性。现在,为了使其正常工作,您需要禁用子列表回收视图的垂直滚动。

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

这样做,所有垂直滚动事件都将由父级 Recycler View 处理。


1
有没有办法让innerRV处理自己的scrollEvents? - RamPrasadBismil

-3

您不需要将recyclerView放在另一个recyclerView中。这没有意义。如果您想将它们放在单个Layout XML中,请按照以下步骤操作:

  • 将NestedScrollView设置为父级
  • 在NestedScrollView内创建LinerLayout
  • 将RecyclerView放置在NestedScrollView中

    <android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
    
                <android.support.v7.widget.RecyclerView
                    android:id="@+id/firstRecycler"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>
    
                <android.support.v7.widget.RecyclerView
                    android:id="@+id/secondRecycler"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>
    
            </LinearLayout>
    </android.support.v4.widget.NestedScrollView>
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接