2

I am trying to create a scroll-able area which will contain various sections of the following types:

  • Horizontal Recycling Section

  • Vertical Recycling Section

  • Text Section

The approach I am taking is to have a NestedRecyclerView as the parent scroll view for all the child sections. This view looks like so:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <com.google.android.material.appbar.AppBarLayout
            android:id="@+id/mynav_appbarLayout"
            android:background="?attr/themeToolbarBg"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <include
                android:id="@+id/mynav_toolbar"
                layout="@layout/actionbar_toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </com.google.android.material.appbar.AppBarLayout>

        <androidx.core.widget.NestedScrollView
            android:id="@+id/nestedScrollView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true"
            app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">

            <LinearLayout
                android:id="@+id/content"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"/>

        </androidx.core.widget.NestedScrollView>

    </androidx.coordinatorlayout.widget.CoordinatorLayout>
</layout>

Then, for each section type I am creating a corresponding view binding and adding it as a child to the LinearLayout which is inside the NestedScrollView.

There are 2 types of section layout, one which is a simple TextView (which I will omit here as it is not relevant) the other of which is a view which contains a RecyclerView. The layout manager for this RecyclerView is created dynamically depending on whether the section it is to be used for is a horizontal or vertical section.

The layout with the RecyclerView in looks like so:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

    <LinearLayout
        android:id="@+id/content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:focusable="true"
        android:focusableInTouchMode="true">

        <TextView
            android:id="@+id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="24dp"
            android:layout_marginTop="8dp"/>

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/fooBarsRecycler"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginStart="16dp"
            android:layout_marginTop="8dp"
            android:nestedScrollingEnabled="false"
            app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"/>
    </LinearLayout>
</layout>

Now, when I am adding these views to the parent NestedScrollView's LinearLayout and setting up the LayoutManager for the associated RecyclerView to orientation Horizontal it works fine, but, when I use orientation Vertical (which is the same orientation as the NestedScrollView) the RecyclerView is NOT recycling views. Obviously this is leading to unacceptable performance.

After doing about a days worth of research and banging my head against the wall it appears that having a RecyclerView nested within a NestedScrollView with the same orientation as the NestedScrollView causes the RecyclerView to lose it's recycler functionality.

As you can hopefully see from the above layout, I have tried all the suggestions I could find, making sure the RecyclerView's height is not wrap_content, using layout_behaviour, setting the NestedRecyclerView to fill view port and so on.

I have exhausted 6 pages of google search around this issue and have tried every suggestion I have found either on SO or blogs and nothing is working.

Oddly, if I swap out the NestedScrollView for a ScrollView, the vertical RecyclerView regains it's recycler functionality, but now scrolls independently of the parent ScrollView which doesn't meet our requirements.

Is this a solved problem or do I need to rethink my entire solution? I.e. am I just missing an attribute or doing something wrong in the XML or is it fundamentally an issue with using a RecyclerView inside a NestedScrollView with the same orientation?

Here is the list of resources, the suggestions of which I have tried exhaustively to no avail:

How to use RecyclerView inside NestedScrollView?

How to use RecyclerView inside NestedScrollView

Recycler view inside NestedScrollView causes scroll to start in the middle

https://android.jlelse.eu/recyclerview-within-nestedscrollview-scrolling-issue-3180b5ad2542

https://medium.com/@mujtahidah/load-more-recyclerview-inside-nested-scroll-view-and-coordinator-layout-4f179dc01fd

https://github.com/google/flexbox-layout/issues/400

https://www.reddit.com/r/androiddev/comments/8oj8cb/having_recyclerview_inside_a_nestedscrollview_is/

https://github.com/mikepenz/FastAdapter/issues/447

https://www.reddit.com/r/androiddev/comments/bixl6r/nestedscrollview_recyclerview/

View Recycling not happens with Multiple Recyclerview inside NestedScrollView

How to make RecyclerView do recycling inside NestedScrollView?

https://code-examples.net/en/q/1d90611

As per a suggestion in the comments, I could model this with a multi type adapter, which is something I have done before but for this particular problem I am not sure this approach will work.

I think the comment is suggesting I model it like so:

Suggestion

Where the adapter would adapt types:

  • Horizontal Section
  • Text Section
  • Card Section

But, the requirement is this:

Actual

So, as you can hopefully see, the RecyclerView will have a LinearLayoutManager with orientation Vertical, but, once we hit the cards, they have to be laid out in a grid fashion, which of course the LinearLayoutManager does not support. So, perhaps I can have the final section be another RecyclerView with a GridLayoutManager? But, I tried this last night and it didn't work, there were scrolling issues as the bottom most RecyclerView is scrolling vertically within the outermost RecyclerView which is also scrolling vertically.

Thomas Cook
  • 2,861
  • 1
  • 13
  • 33
  • Do you have reference to them somewhere else from RecyclerView? If you do then garbage collector will not delete them. – Ferrux Nebiyev Sep 12 '19 at 13:46
  • Nope, the recycler view is correctly setup. As I say, if I swap NestedScrollView for ScrollView the recyclers work fine, it something to do with using RecyclerView inside NestedScrollView – Thomas Cook Sep 12 '19 at 13:54
  • As you find out, the recycler view inside a nested scroll view with a same orientation loses its recycling ability. A better approach to handle your case is to use only one recycler view with a multi-type adapter that handles several item view types. For instance, your item view types are: a horizontal recycler view type, a normal view type like your original adapter and finally, a text section type. – VnM Sep 12 '19 at 14:22
  • @VahidMohammadi - That is a pattern I have implemented before, but in this case it is slightly more complex as the 3 view types are: Horizontal recycler view (fair enough) Text view (easy) Vertical recycler view with grid layout (not so easy) If the vertical recycler view type did not require the grid layout this problem would be easily solved by your suggestion, but the grid kind of throws a spanner in the works. – Thomas Cook Sep 12 '19 at 14:33
  • I am going to edit my question to further explain why I don't think it's going to be straightforward to model this with a multi type adapter – Thomas Cook Sep 12 '19 at 14:38
  • 1
    @ThomasCook for your problem the work you can do is using the GridLayoutManager with span count of 3. The 3 indicate the maximum number of columns that can be existed in your grid layouts. Then on your layoutManager attach a SpanSizeLookup through the setSpanSizeLookup(). By this way, you can manage the span counts of recycler view by the item position. The better approach is getting the item type first by adapter.getItemViewType(position) and then return the span count by the type. – VnM Sep 12 '19 at 15:17
  • 1
    Yup, on it now! Hallelujia – Thomas Cook Sep 12 '19 at 16:07

0 Answers0