Gabriel
Gabriel

Reputation: 688

Recyclerview binds all views at the same time

I have a vertical recyclerview (with a GridLayoutManager) inside another recyclerview (with LinearLayoutManager). The problem I am facing right now is that, the inner recyclerview (with GridLayoutManager) binds all of it's items at the same time, even the views that are not on the screen at the moment (onBindViewHolder() gets called for all of its items).

To give you more information, in my layout file, I put height of my recycler view as wrap_content.

I think the problem is, since there are 2 nested vertically recyclerviews, when the parent RV wants to measure its children and the children is another RV, in onMeasure() it computes the size needed for the entire RV, not just the portion that it wants to bind on the screen.

Any idea how to solve this?

Here is the layout file for my outer 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>

And here is the code for my inner 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.: I'm using this adapter delegate for my outer recyclerview: https://github.com/sockeqwe/AdapterDelegates

Upvotes: 19

Views: 5691

Answers (5)

Gabriel
Gabriel

Reputation: 688

I could solve my issue by using only one Recyclerview, where it has a grid layout, and based on the component items i'm adding into it, i change the spancount for that. Basically instead of adding the inner recyclerview, i add the items that were supposed to go to the inner recyclerview, to the outer recyclerview.

Upvotes: -3

Robin Dijkhof
Robin Dijkhof

Reputation: 19288

I think nested recyclerviews are a very bad idea. When i try to scroll, which recyclerview has to respond the the scolling, the parrent or child.

That is why I think you are looking for the ExpandableListView? That's limited to only two levels of listings, but that sounds like it would work for your needs). It also solves the soling issue.

It would look something like this:

enter image description here

EDIT: even nested ExpandableListViews are possible:

enter image description here

EDIT: check this lib for horizontal scroling

Upvotes: 6

shashank vaibhav
shashank vaibhav

Reputation: 1

so what happens here when you place a scrollview(no fixed size because of wrap content) inside another scrollview(again no fixed size because of wrap content),both nested scroll view fails to render.

So there is two solutions--

1- Either you will have to think of alternative solution for nested scrollviews 2- You can give outside recyclerview cell fixed height so that inside recycler view can get some fixed layout to render itself.

Upvotes: 0

abhishesh
abhishesh

Reputation: 3316

This is a known bug.
You should not put a RecyclerView inside another RecyclerView because RecyclerView gives its children infinite space.
Hence the inner RecyclerView keeps measuring till the dataset is exhausted.
Try setting setAutoMeasureEnabled(false) to false on layout manager or you can solve this problem by using a wrapper adapter instead of inner recycler view.

Upvotes: 4

John Gallagher
John Gallagher

Reputation: 535

The first thing you need to know is that, when you nest scrolling layouts, the inner ones will get infinity allowed height, effectively making them wrap_content. There is in fact a relatively easy way to fix this problem. Say I had two nested RecyclerViews such as these, in this case vertically oriented.

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

The inner recyclerView here will bind all of it's children immediately every time because, from it's position, your screen will have infinite height.

The solution is to set the height of your inner recyclerview to some static value, not wrap_content or match parent, as either of those will simply fill up the outer recyclerview with one view that will all be bound at once due to it's large height. If you make the height of the inner recyclerview the same as the display's height, you should see your problem go away.

Here is an implementation that will not bind all children at once:

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

Note the layout_height of the inner RecyclerView is now a fixed value pulled from the dimensions file. You yourself will have to come up with a reasonable value to put there.

Side Note: In order to make all of this work and for scrolling to work properly, you may have to play around with the parameter: NestedScrollingEnabled in your RecyclerViews - there are several known bugs relating to this that you may need to work around.

i.e.: innerRecyclerView.setHasFixedSize(true); and innerRecyclerView.setNestedScrollingEnabled(false).

Upvotes: 0

Related Questions