How to put RecyclerView inside NestedScrollView?

recyclerview inside scrollview
recyclerview inside nestedscrollview performance
recyclerview inside nestedscrollview pagination
recyclerview inside nestedscrollview not showing
recyclerview inside nestedscrollview not recycling
multiple recyclerview inside nestedscrollview
multiple recyclerview inside scrollview android
recyclerview inside nestedscrollview pagination github

With creation of NestedScrollView you can put scrolling view inside another scrolling view as long as those implement NestedScrollingChild and NestedScrollingParent correctly.

(This is not bad design pattern "Ian Lake (from Google) actually recommends putting a RecyclerView inside a nestedscrollview here: plus.google.com/u/0/+AndroidDevelopers/posts/9kZ3SsXdT2T")

I want to put RecyclerView inside NestedScrollView and fortunately RecyclerView implements NestedScrollingChild so you can put it inside NestedScrollView.

public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild

I have read these posts:

How to use RecyclerView inside NestedScrollView?

NestedScrolling with NestedScrollView, RecyclerView (Horizontal), inside a CoordinatorLayout

But the problem with most voted solution is, it calls all of the items of RecyclerView so for example if it is an endless RecyclerView and when the user reaches the end of the list you want to make a network request then with that solution the RecyclerView calls server repeatedly because it automatically reaches the last item of RecyclerView.

Anyway, how to set parameter so I can put RecyclerView inside NestedScrollView.(actually I want to put a viewgroup like framelayout or relativelayout as a single childe of nestedscrollview and then I want to put recyclerview inside framelayout or relativelayout)

When I put RecyclerView inside NestedScrollView there is nothing to display.


In order to create a sample project you can use cheesesquare and change the CheeseDetailActivity to have a RecyclerView.


Although the answer of BNK is not correct but BNK has tried a lot. So I award him the bounty. Still looking for nice solution....

The following is my new updated answer:

<android.support.v4.widget.NestedScrollView
        android:id="@+id/scrollview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.CardView
                android:id="@+id/cardview1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/card_margin">

                <LinearLayout
                    style="@style/Widget.CardContent"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="Info CardView1"
                        android:textAppearance="@style/TextAppearance.AppCompat.Title" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@string/cheese_ipsum" />

                </LinearLayout>

            </android.support.v7.widget.CardView>

            <android.support.v7.widget.CardView
                android:id="@+id/cardview2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/cardview1"
                android:layout_margin="@dimen/card_margin">

                <LinearLayout
                    style="@style/Widget.CardContent"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="Info CardView2"
                        android:textAppearance="@style/TextAppearance.AppCompat.Title" />

                    <TextView
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        android:text="@string/cheese_ipsum" />

                </LinearLayout>

            </android.support.v7.widget.CardView>

            <android.support.v7.widget.RecyclerView
                android:id="@+id/recyclerview"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/cardview2"
                android:clipToPadding="false"
                android:paddingTop="0dp"/>

        </RelativeLayout>

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

In Activity:

        RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(true); // true: with header
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);            
        final MyLinearLayoutManager layoutManager = new MyLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false, getScreenHeight(this));
        // final CustomLinearLayoutManager layoutManager = new CustomLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(recyclerViewAdapter);  
        // recyclerView.setNestedScrollingEnabled(false); // Disables scrolling for RecyclerView, however, CustomLinearLayoutManager used instead of MyLinearLayoutManager

I have also updated to My GitHub's sample project

Screenshot:


RecyclerView within NestedScrollView Scrolling Issue, Now what kinda problem occurred when we used nestedScrollView and put recyclerView inside nestedScrollView , it scrolls at various speeds� So put RecyclerView inside NestedScrollView directly will unfortunately display nothing. However, there is a way to put the recyclerview inside the NestedScrollView indirectly - just use a frameLayout as the third party to hold your recyclerview. This is the framelayout which holds the nested recyclerview in your activity class:

Here is solution to call server only when you are realy need to load more data. In this way you can put your endless RecyclerView and many other views inside NestedScrollView. For me it is working well.

1. Create EndlessParentScrollListener class to handle scroll events from NestedSrollView.

public abstract class EndlessParentScrollListener implements NestedScrollView.OnScrollChangeListener {
        // The current offset index of data you have loaded
        private int currentPage = 0;
        // The total number of items in the dataset after the last load
        private int previousTotalItemCount = 0;
        // True if we are still waiting for the last set of data to load.
        private boolean loading = true;
        // Sets the starting page index
        private int startingPageIndex = 0;
        // The minimum amount of pixels to have below your current scroll position
        // before loading more.
        private int visibleThresholdDistance = 300;

        RecyclerView.LayoutManager mLayoutManager;

        public EndlessParentScrollListener(RecyclerView.LayoutManager layoutManager) {
            this.mLayoutManager = layoutManager;
        }

        @Override
        public void onScrollChange(NestedScrollView scrollView, int x, int y, int oldx, int oldy) {
            // We take the last son in the scrollview
            View view = scrollView.getChildAt(scrollView.getChildCount() - 1);
            int distanceToEnd = (view.getBottom() - (scrollView.getHeight() + scrollView.getScrollY()));

            int totalItemCount = mLayoutManager.getItemCount();
            // If the total item count is zero and the previous isn't, assume the
            // list is invalidated and should be reset back to initial state
            if (totalItemCount < previousTotalItemCount) {
                this.currentPage = this.startingPageIndex;
                this.previousTotalItemCount = totalItemCount;
                if (totalItemCount == 0) {
                    this.loading = true;
                }
            }

            // If it’s still loading, we check to see if the dataset count has
            // changed, if so we conclude it has finished loading and update the current page
            // number and total item count.
            if (loading && (totalItemCount > previousTotalItemCount)) {
                loading = false;
                previousTotalItemCount = totalItemCount;
            }

            // If it isn’t currently loading, we check to see if we have breached
            // the visibleThreshold and need to reload more data.
            // If we do need to reload some more data, we execute onLoadMore to fetch the data.
            // threshold should reflect how many total columns there are too
            if (!loading && distanceToEnd <= visibleThresholdDistance) {
                currentPage++;
                onLoadMore(currentPage, totalItemCount);
                loading = true;
            }
        }

        // Defines the process for actually loading more data based on page
        public abstract void onLoadMore(int page, int totalItemsCount);
    }

2. Set listener

private void initRecycler() {  
        //TODO init recycler adapter here

        recycler.setNestedScrollingEnabled(false);          
        LinearLayoutManager _layoutManager = new LinearLayoutManager(this);
        recycler.setLayoutManager(_layoutManager);
        NestedScrollView scrollView = (NestedScrollView) findViewById(R.id.scrollView);
        scrollView.setOnScrollChangeListener(new EndlessParentScrollListener(_layoutManager) {
                @Override
                public void onLoadMore(int page, int totalItemsCount) {                     
                    if (loadedItemCount < serverItemsCount)
                        customLoadMoreDataFromApi();
                }
            });
        customLoadMoreDataFromApi();
    }

Short xml if someone find it usefull:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/background_light"
        android:fitsSystemWindows="true">


        <android.support.design.widget.AppBarLayout>
            ...
        </android.support.design.widget.AppBarLayout>

        <android.support.v4.widget.NestedScrollView
            android:id="@+id/scrollView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            android:scrollbars="vertical"
            android:scrollbarAlwaysDrawVerticalTrack="true"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical"
                android:scrollbarAlwaysDrawVerticalTrack="false"
                android:scrollbars="vertical">

                <!-- some views goes here-->

                <android.support.v7.widget.RecyclerView
                    android:id="@+id/recyclerFeed"
                    android:scrollbars="vertical"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

                <!-- and possibly here-->

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

    </android.support.design.widget.CoordinatorLayout>

How to use RecyclerView inside NestedScrollView in Android?, demonstrates how do I use RecyclerView inside NestedScrollView in Add the following dependency in the build.gradle (Module: app) The solution for this is we need to use nestedScrollView instead of scrollview like the below code snippet: Now what kinda problem occurred when we used nestedScrollView and put recyclerView inside nestedScrollView , it scrolls at various speeds depending on gestures.

So put RecyclerView inside NestedScrollView directly will unfortunately display nothing. However, there is a way to put the recyclerview inside the NestedScrollView indirectly - just use a frameLayout as the third party to hold your recyclerview.

This is the framelayout which holds the nested recyclerview in your activity class:

    <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:context=".ExampleFragment"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true"
            >
        </android.support.v4.widget.NestedScrollView>
   </FrameLayout>

Put your fragment into the framelayout (code sits within the activity class):

 ExampleFragment exampleFragment = new ExampleFragment();

    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.add(R.id.container, exampleFragment);
    ft.commit();

In your exampleFragment, you can then put your recyclerview.

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/post_container"
        android:background="#E0E0E0">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/my_recycler_view"
                android:scrollbars="vertical"

                android:layout_width="match_parent"
                android:layout_height="match_parent">
            </android.support.v7.widget.RecyclerView>


    </RelativeLayout>

This is the fragment code:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    super.onCreateView(inflater, container, savedInstanceState);
            llLayout = (RelativeLayout) inflater.inflate(R.layout.example_fragment_layout, container, false);
                    mRecyclerView = (RecyclerView) llLayout.findViewById(R.id.my_recycler_view);

The following is the CheeseSquare XML layout you should have:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/detail_backdrop_height"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:fitsSystemWindows="true">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginStart="48dp"
            app:expandedTitleMarginEnd="64dp">

            <ImageView
                android:id="@+id/backdrop"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                app:layout_collapseMode="parallax" />

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_collapseMode="pin" />

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

   <FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:context=".ExampleFragment"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fillViewport="true"
            >
        </android.support.v4.widget.NestedScrollView>
   </FrameLayout>

    <android.support.design.widget.FloatingActionButton
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|right|end"
        android:src="@drawable/ic_discuss"
        android:layout_margin="@dimen/fab_margin"
        android:clickable="true"/>

</android.support.design.widget.CoordinatorLayout>

Load More RecyclerView inside Nested Scroll View and Coordinator , Thanks adding scoll listener to the nested scrollview instead of recycler view helped..but i didnt use the first if statatements inside on scroll� I experience one issue putting my RecyclerView inside the NestedScrollView. I realized that scrolling the content of my RecyclerView slacked. I later realized that my RecyclerView was receiving the scrolling event and therefore was conflicting with the scrolling behavior of the NestedScrollView.

I have wasted at least a week behind this and the only solution that works is to remove the nestedscrollview. I know that is not the answer to this particular question of adding recyclerview inside nestedscrollview, but to make the recyclerview to actually recycle the view, you HAVE TO REMOVE the nestedscrollview. If you happen to have multiple view inside instead of just the recyclerview, You have to add them as items of the recyclerview by setting different viewholders, and then adding

app:layout_behavior="@string/appbar_scrolling_view_behavior"

to the recyclerview or the parent of recyclerview(the parent cannot have any other view other than Recyclerview for this to work).

In my case, the requirement was as follows:

  <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:fitsSystemWindows="true"
        app:layout_constraintTop_toTopOf="parent">

        <!-- Scrollable view here -->

        <com.google.android.material.appbar.AppBarLayout
            ....   >

            <com.google.android.material.appbar.CollapsingToolbarLayout
                ....>

                <androidx.appcompat.widget.Toolbar
                    ....>

                    <include
                        android:id="@+id/toolbar_header_view"
                        .... />
                </androidx.appcompat.widget.Toolbar>

                <include layout="@layout/widget_header" />
            </com.google.android.material.appbar.CollapsingToolbarLayout>
        </com.google.android.material.appbar.AppBarLayout>

        <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
            ....>
            <LinearLayout orientation="vertical" ....>
                <View .../>  <!-- I needed to have these two views along with recyclerview and i wanted them to do nestedscroll along with recyclerview -->
                <View .../>
                <androidx.recyclerview.widget.RecyclerView
                .... />
        </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

I needed to have two views before recyclerview and I wanted them to do nestedscroll along with recyclerview. The only thing that worked was by removing these to views and adding them as the first two items of recyclerview, and then adding

app:layout_behavior="@string/appbar_scrolling_view_behavior"

to the swipetorefresh layout

Hope this helps someone. I will add more info If required.

How to use RecyclerView inside NestedScrollView?, I have Viewpager and RecyclerView inside the NestedScrollView. After adding below lines. recyclerView. In your layout add RecyclerView like this:. So I need the NestedScrollView to allow users to scroll screen to see full RecyclerView – TOP Jun 9 '17 at 9:33 Yes you can do this using NestedScrollView too.Just Add this line if you are using NestedScrollView. recyclerView.setNestedScrollingEnabled(false); – Akash Jun 9 '17 at 9:34

Android – RecyclerView inside NestedScrollView Example, We are going to add a LinearLayout as a child to NestedScrollView. Inside the LinearLayout, add an ImageView on top and RecyclerView under it. This is where the main tricks lies. In other to enjoy smooth scrolling with the android RecyclerView put inside the NestedScrollView, we are going to set the method setNestedScrollingEnabled(false) to false. Finally, set the ProductAdapter instance to the RecyclerView object by call the setAdapter() method of the class.

Having RecyclerView inside a NestedScrollView is calling , Having RecyclerView inside a NestedScrollView is calling onBindView for all companies want some high-level engineering people, but why put through all� RecyclerView steals focus when inside a NestedScrollView, When I put a RecyclerView inside a nested scrollview, the screen always jumps to the top of the RecyclerView instead of the top of the page. Here Great, this also works when having Horizontal RecyclerView(s) inside a Vertical RecyclerView.

RecyclerView inside NestedScrollView causes RecyclerView to , If you put a RecyclerView inside a NestedScrollView, it will automatically inflate in my app that requires putting different views together as a NestedScrollView. donc mettre RecyclerView dans NestedScrollView directement n'affichera malheureusement rien. Cependant, il y a un moyen de placer le recyclerview dans le NestedScrollView indirectement - il suffit d'utiliser un frameLayout comme tiers pour tenir votre recyclerview.

Comments
  • RecyclerView calls server repeatedly because it automatically reaches the last item of RecyclerView.. Are you sure about this ?
  • @Ramesh yes with suggested solution it calls the last visible item which is the last item of current data. it is not the real last visible item.
  • try this link.
  • Any news on this? I am facing the same problem too... frustrating
  • @mmlooloo nope! non of the answers worked! I ended up with a recyclerview and a vertical linear layout manager, and replacing inner recyclerview with custom rows, for example four items in a row!!
  • thanks but adding android:fillViewport="true" without adding framelayout dose not work. thanks again
  • Thank you, right now I have to fix some other part of my main project, when I reach that UI I will surely try your new sample. I have understand your trick, it seems work nicely. again thanks.
  • Hi guys! Super interesting conversation! I was checking out @BNK's project (github.com/ngocchung/NestedScrollView) and started playing with it a little bit, since I needed to do something similar. I have one question though, when the content ABOVE the recyclerview (CardViews) fit in the screen without the need of scrolling down, the content gets scrolled down automatically to the start of the Recyclerview. You can test this by removing or commenting one of the CardViews at the top of content_main.xml. Is there a workaround for this behaviour? Ideally, I do not want this autoscroll
  • @acrespo thanks for your comment. For your issue, please add android:descendantFocusability="blocksDescendants" in the first RelativeLayout under the NestedScrollView
  • if i put recycleview inside NestedScrollView it calling bindviewholder for all row
  • @mmlooloo you should submit this answer
  • is all children of the RecyclerView still visible due to being a child of NestedScrollView and would cause OutOfMemoryException like this? or it is safe?