RecyclerView一次性绑定所有视图。

19

我有一个垂直的recyclerview(使用GridLayoutManager)放在另一个recyclerview(使用LinearLayoutManager)内。我现在面临的问题是,内部的recyclerview(使用GridLayoutManager)会将所有项目同时绑定,即使当前屏幕上没有这些视图(对于其所有项都调用onBindViewHolder())。

为了给您更多信息,在我的布局文件中,我将recyclerview的高度设置为wrap_content

我认为问题在于,由于有两个嵌套的垂直recyclerviews,当父RV想要测量其子项并且子项是另一个RV时,在onMeasure()中它计算了整个RV所需的大小,而不仅仅是它想要绑定到屏幕上的部分。

有什么解决方法吗?

以下是我的外部recyclerview的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
    android:id="@+id/component_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

</FrameLayout>

这是我的内部RecyclerView的代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/gutter"
android:paddingBottom="@dimen/gutter">

<TextView
    android:id="@+id/title_text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="@dimen/gutter"
    android:textSize="30sp"
    android:textColor="@android:color/white"
    android:fontFamily="sans-serif-thin"/>

<android.support.v7.widget.RecyclerView
    android:id="@+id/my_slider"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

</LinearLayout>

P.S.:我在我的外部recyclerview中使用此适配器代理: https://github.com/sockeqwe/AdapterDelegates


你对问题的理解是正确的 - RecyclerView具有无限长度,因此子RV将认为它适合每个视图。我不会给出答案,因为我不确定,但我认为你需要制作一个自定义布局管理器。 - Gabe Sechan
5个回答

6

我认为嵌套的RecyclerView是一个非常糟糕的想法。当我尝试滚动时,哪个RecyclerView应该响应滚动,父级还是子级。

这就是为什么我认为你正在寻找ExpandableListView?它只限于两个级别的列表,但这似乎适合您的需求。它也解决了滚动问题。

它看起来会像这样:

enter image description here

编辑:即使是嵌套的可扩展列表视图也是可能的:

enter image description here

编辑:检查this库以进行水平滚动。

如果您有多个水平列表,您会如何处理? - Amir
实际上在我的情况下有所不同,我不能在这里放任何设计截图,但基本上是一堆组件在外部RV中,其中一个组件可能是具有网格布局的RV。因此,我认为这并不一定是一个坏主意,这取决于你想做什么。你的解决方案对我不起作用,因为我有的设计不同。 - Gabriel
你能添加一个小草图吗?用画图或其他软件画一下? - Robin Dijkhof

4

这是一个已知的错误。
不应该在另一个RecyclerView中放置一个RecyclerView,因为RecyclerView会给其子项提供无限空间。
因此,内部的RecyclerView会一直测量,直到数据集用尽。
可以通过在布局管理器上将setAutoMeasureEnabled(false)设置为false,或者使用包装适配器而不是内部RecyclerView来解决此问题。


如果这是一个已知的 bug,你能否请指出在 Google 论坛中报告的 bug? - Gabriel
我建议您使用包装适配器。 - abhishesh
你能在这里或者Github上发布一些代码吗?我会使用你的代码进行解释。 - abhishesh
适配器是Recycler View的重要组成部分。 - abhishesh
我的意思是,通过包装适配器,无论您在内部回收视图适配器中进行的绑定部分是什么,都可以在外部回收视图适配器中完成。将内部回收视图的子项视为外部回收视图的直接子项。这样,您就不需要内部回收视图了。 - abhishesh
显示剩余4条评论

0

当你将一个没有固定大小的滚动视图(因为包裹内容)放置在另一个没有固定大小的滚动视图中时,两个嵌套的滚动视图都无法渲染。

所以有两种解决方案--

1- 要么你必须考虑嵌套滚动视图的替代解决方案 2- 你可以给外部的可回收视图单元格设置固定高度,这样内部的可回收视图就能获得一些固定布局来进行渲染。


#1) 没有其他选择,因为这是基于设计的。 #2) 这不会起作用,因为如果我给它一个固定的高度,它就无法滚动。 - Gabriel

0
首先需要知道的是,当您嵌套滚动布局时,内部布局将获得无限允许的高度,从而使它们有效地成为wrap_content。实际上,有一种相对简单的方法来解决这个问题。比如我有两个嵌套的RecyclerView,就像这样,这种情况下是垂直方向的。
<RecyclerView 
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical>
    <View .../>
    <!-- other stuff -->
    <RecyclerView 
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical"/>
</RecyclerView>

这里的内部recyclerView每次都会立即绑定所有子项,因为从它的位置来看,您的屏幕高度是无限的。

解决方案是将内部recyclerview的高度设置为某个静态值,而不是wrap_content或match_parent,因为这两者都会简单地用一个视图填充外部recyclerview,由于其高度很大,所有视图都将一次性绑定。如果您将内部recyclerview的高度设置为显示器的高度相同,则应该可以解决问题。

这是一个不会一次性绑定所有子项的实现:

<RecyclerView 
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    android:orientation="vertical>
    <View .../>
    <!-- other stuff -->
    <RecyclerView 
         android:layout_width="match_parent"
         android:layout_height="@dimen/screen_height"
         android:orientation="vertical"/>
</RecyclerView>

请注意,内部RecyclerView的layout_height现在是从dimensions文件中提取的固定值。你自己需要想一个合理的值放在那里。
顺便提一下:为了使所有这些工作正常,并且让滚动正常工作,您可能需要调整RecyclerViews中的NestedScrollingEnabled参数-有几个已知的与此相关的错误,您可能需要解决。
例如:innerRecyclerView.setHasFixedSize(true);和innerRecyclerView.setNestedScrollingEnabled(false)。

1
我之前尝试过这个解决方案,问题是滚动不再起作用了。我甚至将嵌套滚动设置为true,但还是没有成功。 - Gabriel
如果我执行 innerRecyclerView.setNestedScrollingEnabled(false);,那么我该如何滚动查看所有在RV中的项目?在这种情况下,它只会显示RV中的一小部分项目。 - Gabriel
我猜你已经尝试了setHasFixedSize(boolean)和setNestedScrollingEnabled(boolean)的所有排列组合。你尝试给内部recyclerview设置一个最大高度了吗?如果没有,我建议你先尝试这个来解决你的初始问题,如果还不行,能否在你的问题中提供一些代码帮助我们找出问题所在? - John Gallagher
我很想看看你的RecyclerView的XML,以及你在哪里将内部RecyclerView绑定到外部RecyclerView。我今天会自己实现这个功能,并尝试与您联系。 - John Gallagher
我的外部RV持有一堆组件,其中一个组件是使用网格布局的RV。 - Gabriel
显示剩余2条评论

-3

我可以通过仅使用一个具有网格布局的RecyclerView解决我的问题,并根据我添加到其中的组件项更改spancount。基本上,我不是添加内部RecyclerView,而是将应该进入内部RecyclerView的项目添加到外部RecyclerView。


这不是一个真正的解决方案。 - Ahmet K

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