I have a view that acts like BottomSheetBehavior and this view has ViewPager2 inside. Each ViewPager2's page is a vertical RecyclerView. The issue is that BottomSheet doesn't scroll down when current vertical RecyclerView (which is a page of ViewPager) can't scroll vertically anymore. Everything works file when instead of ViePager I have only one vertical RecyclerView.
The temporary solution is to wrap ViewPager with NestedScrollView but it's horrible for performance and has it's own bugs.
The original layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/core"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#C7C7C7"
tools:context=".MainActivity">
<LinearLayout
android:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:elevation="8dp"
android:orientation="vertical"
app:behavior_hideable="true"
app:behavior_peekHeight="300dp"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_gravity="center_horizontal"
app:tabGravity="center"
app:tabMode="scrollable" />
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
[Here's how it looks (sorry for the gif quality)]
I've found a solution for this case, I set isNestedScrollingEnabled = false for inner RecyclerView so that BottomSheetBehavior finds another scrolling view
viewPager.children.find { it is RecyclerView }?.let {
(it as RecyclerView).isNestedScrollingEnabled = false
}
BottomSheetBehaviour only detects the first scrollable view. So it is always recommended to use only one scrollable view inside of it.
For More information check this answer bottomsheetbehavior-with-two-recyclerview
And this one also Scroll not working for multiple RecyclerView in BottomSheet
If you really want to have the two scrollable views I recommend you to take a look at this library also AndroidSlidingUpPanel
For my app I am using a RecyclerView inside a ScrollView where the RecyclerView has a height based on its content using this library. Scrolling is working but it's not working smoothly when I scroll over the RecyclerView. When I scroll over the ScrollView itself it is scrolling smoothly.
The code I am using to define the RecyclerView:
LinearLayoutManager friendsLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext(), android.support.v7.widget.LinearLayoutManager.VERTICAL, false);
mFriendsListView.setLayoutManager(friendsLayoutManager);
mFriendsListView.addItemDecoration(new DividerItemDecoration(getActivity().getApplicationContext(), null));
The RecyclerView in the ScrollView:
<android.support.v7.widget.RecyclerView
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:id="#+id/friendsList"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
Try doing:
RecyclerView v = (RecyclerView) findViewById(...);
v.setNestedScrollingEnabled(false);
As an alternative, you can modify your layout using the support design library. I guess your current layout is something like:
<ScrollView >
<LinearLayout >
<View > <!-- upper content -->
<RecyclerView > <!-- with custom layoutmanager -->
</LinearLayout >
</ScrollView >
You can modify that to:
<CoordinatorLayout >
<AppBarLayout >
<CollapsingToolbarLayout >
<!-- with your content, and layout_scrollFlags="scroll" -->
</CollapsingToolbarLayout >
</AppBarLayout >
<RecyclerView > <!-- with standard layoutManager -->
</CoordinatorLayout >
However this is a longer road to take, and if you are OK with the custom linear layout manager, then just disable nested scrolling on the recycler view.
Edit (4/3/2016)
The v 23.2 release of the support libraries now includes a factory “wrap content” feature in all default LayoutManagers. I didn’t test it, but you should probably prefer it to that library you were using.
<ScrollView >
<LinearLayout >
<View > <!-- upper content -->
<RecyclerView > <!-- with wrap_content -->
</LinearLayout >
</ScrollView >
I only needed to use this:
mMyRecyclerView.setNestedScrollingEnabled(false);
in my onCreateView() method.
Thanks a lot!
You can use this way either :
Add this line to your recyclerView xml file :
android:nestedScrollingEnabled="false"
Or in java code :
RecyclerView.setNestedScrollingEnabled(false);
Hope this helped .
You can try with both the ways with XML and programmatically. But the issue you may face is (below API 21) by doing it with XML will not work . So it's better to set it programmatically in your Activity / Fragment.
XML code:
<android.support.v7.widget.RecyclerView
android:id="#+id/recycleView"
android:layout_width="match_parent"
android:visibility="gone"
android:nestedScrollingEnabled="false"
android:layout_height="wrap_content"
android:layout_below="#+id/linearLayoutBottomText" />
Programmatically:
recycleView = (RecyclerView) findViewById(R.id.recycleView);
recycleView.setNestedScrollingEnabled(false);
Using Nested Scroll View instead of Scroll View solved my problem
<LinearLayout> <!--Main Layout -->
<android.support.v4.widget.NestedScrollView>
<LinearLayout > <!--Nested Scoll View enclosing Layout -->`
<View > <!-- upper content -->
<RecyclerView >
</LinearLayout >
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
I had similar issues (I tried to create a nested RecyclerViews something like Google PlayStore design). The best way to deal with this is by subclassing the child RecyclerViews and overriding the 'onInterceptTouchEvent' and 'onTouchEvent' methods. This way you get complete control of how those events behave and eventually scrolling.
Replacing ScrollView with NestedScrollView resulted into smooth scrolling to the bottom.
Summary of all answers (Advantages & Disadvantages)
For single recyclerview
you can use it inside Coordinator layout.
Advantage - it will not load entire recyclerview items. So smooth loading.
Disadvantage - you can't load two recyclerview inside Coordinator layout - it produce scrolling problems
reference - https://stackoverflow.com/a/33143512/3879847
For multiple recylerview with minimum rows
you can load inside NestedScrollView
Advantage - it will scroll smoothly
Disadvantage - It load all rows of recyclerview so your activity open with delay
reference - https://stackoverflow.com/a/33143512/3879847
For multiple recylerview with large rows(more than 100)
You must go with recyclerview.
Advantage - Scroll smoothly, load smoothly
Disadvantage - You need to write more code and logic
Load each recylerview inside main recyclerview with help of multi-viewholders
ex:
MainRecyclerview
-ChildRecyclerview1 (ViewHolder1)
-ChildRecyclerview2 (ViewHolder2)
-ChildRecyclerview3 (ViewHolder3)
-Any other layout (ViewHolder4)
Reference for multi-viewHolder - https://stackoverflow.com/a/26245463/3879847
Kotlin
Set isNestedScrollingEnabled to false for every RecyclerView that is under the scrolling view
val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
recyclerView.isNestedScrollingEnabled = false
Using XML Layout
<android.support.v7.widget.RecyclerView
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:id="#+id/friendsList"
android:layout_width="match_parent"
android:nestedScrollingEnabled="false"
android:layout_height="wrap_content" />
Every answer is same here. and i already used what everyone is suggested. Then i found that NestedScrollView is faster then ScrollView so
use
<androidx.core.widget.NestedScrollView
Instead of
<ScrollView
And use this as usual
recycleView.setNestedScrollingEnabled(false);
If you are using VideoView or heavy weight widgets in your childviews keep your RecyclerView with height wrap_content
inside a NestedScrollView with height match_parent
Then scrolling will work smooth as perfectly as you want it.
FYI,
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:nestedScrollingEnabled="false"
android:layout_height="wrap_content"
android:clipToPadding="false" />
</android.support.v4.widget.NestedScrollView>
Thanks Micro this was from your hint!
karthik
you can use ScrollView as a parent and NestedScrollView as a child.
like this:-
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/CL1">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/eventRV"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/CL1" />
</androidx.core.widget.NestedScrollView>
XML code:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false" />
</android.support.v4.widget.NestedScrollView>
in java code :
recycleView = (RecyclerView) findViewById(R.id.recycleView);
recycleView.setNestedScrollingEnabled(false);
Or you can just set android:focusableInTouchMode="true" in your recycler view
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<android.support.constraint.ConstraintLayout
android:id="#+id/constraintlayout_main"
android:layout_width="match_parent"
android:layout_height="#dimen/layout_width_height_fortyfive"
android:layout_marginLeft="#dimen/padding_margin_sixteen"
android:layout_marginRight="#dimen/padding_margin_sixteen"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
<TextView
android:id="#+id/textview_settings"
style="#style/textviewHeaderMain"
android:gravity="start"
android:text="#string/app_name"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
<android.support.constraint.ConstraintLayout
android:id="#+id/constraintlayout_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/padding_margin_zero"
android:layout_marginTop="#dimen/padding_margin_zero"
android:layout_marginEnd="#dimen/padding_margin_zero"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/constraintlayout_main">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.constraint.ConstraintLayout>
This code is working for in ConstraintLayout android
Simple Add this line into your JAVA class
list.setNestedScrollingEnabled(false);
I myself had this issue, there is a recycler view within a scrollview and the scroll doesn't seem to be smooth. The cause for my issue was having the scrollview on top of the recycler view which was not needed for my requirement. So after I removed the scrollview and added the android:scrollbars="vertical" for recycler view, the scrolling was smooth.
After 3 days of research, I solved smooth scroll issue in my project.
The problem is <layer-list> drawable set in the background of item_user.xml file so it takes GPU time for rendering that's why scrolling not smooth. So please dont use complex <layer-list> drawable in the background of adapter item.
My problem is solved by above solution, below option is not useful for me
setNestedScrollingEnabled
setHasFixedSize
setItemViewCacheSize
I am using paging library to load data and populate my recyclerview which is placed inside a nestedscrollview. But it is like, pagination works automatically until all the data fetched from API. I know this is because of the nestedscrollview. But unfortunately my layout needs scrollview as i have a top section other than recyclerview in this fragment.
This is my layout
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
//have a layout here which scrolls with recyclerview
<Recyclerview />
</ConstraintLayout>
</NestedScrollView>
Everything works fine when i do not use nestedscrollview. There is an open issue in googlesamples git repo regsrding this problem.
https://github.com/googlesamples/android-architecture-components/issues/215
Is anyone have idea how can we implement pagination when a recyclerview is inside a scrollview with pagination library from Android jetpack. I know we can implement traditional kind of pagination attaching listener to nestedscrollview, but i am looking to implement pagination with architecture component library.
https://developer.android.com/topic/libraries/architecture/paging/
Using the below code will solve the issue.
Here is the view hierarchy:
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="#+id/coordinator_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appbar_layout"
android:background="#color/white"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:titleEnabled="false">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Put here elements that you need above the recycler view -->
</LinearLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<!-- RecyclerView -->
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:scrollbars="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Note: Be sure that you have given id to CoordinatorLayout and AppBarLayout so that it will retain scroll position on the back stack.
The problem is recyclerview inside nested scrolview. Paging library has nothing to do with it. The behavior would be same if you try to load data on scroll listener of recyclerview.
The paging library does not work well with nestedScroolView. So you have to change your NesteScrollView to ScroolView with android:nestedScrollingEnabled="true", something like this:
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:nestedScrollingEnabled="true"
>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
//have a layout here which scrolls with recyclerview
<Recyclerview />
</ConstraintLayout>
</ScrollView>
I am using the following layout, but unable to get the RecyclerView to scroll(it is not visible on the screen when using this layout, scrolling stops till the NestedScrollView).
I can scroll up to the NestedScrollView and the CollapsingToolbar to collapse, if I remove the entire NestedScrollView then I get the RecyclerView to scroll.
If I keep the linear layout without the NestedScrollView, only the RecyclerView scrolls, the rest of the layout is fixed.
I have also added app:layout_behavior="#string/appbar_scrolling_view_behavior" to the RecyclerView, and have kept the RecyclerView out of the NestedScrollView.
If I add the RecyclerView inside the NestedScrollView, the RecyclerView does not appear.
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="com.example.MainFragment">
<!-- android.support.design.widget.AppBarLayout here
with a android.support.design.widget.CollapsingToolbarLayout
-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<!-- more layout code here -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/large_text"/>
</RelativeLayout>
<View
android:id="#+id/separator"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/colorAccent" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerViewListOfData"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:listitem="#layout/recycler_view"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</LinearLayout>
Ok, if you want to add RecyclerView inside NestedScrollView add this line into RecyclerView in xml file app:layoutManager="LinearLayoutManager".
Example
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/your_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="LinearLayoutManager"/>
</android.support.v4.widget.NestedScrollView>
Then in your SomeActivity.java file where you populate RecyclerView put this line recyclerView.setNestedScrollingEnabled(false); before you setting adapter to RecyclerView.
Example
RecyclerView recyclerView=(RecyclerView)findViewById(R.id.your_recyclerview);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setAdapter(yourAdapter);
I solved it by nesting RecyclerView inside the NestedScrollView and updating the support library for recyclerview
I was using com.android.support:recyclerview-v7:23.0.1
as of Android Support Library, revision 23.2.0 (February 2016)
(refer revision archive here)
Changes for v7 RecyclerView library:
RecyclerView now has an opt-in feature called AutoMeasure which allows RecyclerView.LayoutManager to easily wrap content or
handle various measurement specifications provided by the parent of
the RecyclerView. It supports all existing animation capabilities of
the RecyclerView.
If you have a custom RecyclerView.LayoutManager, call setAutoMeasureEnabled(true) to start using the new AutoMeasure API.
All built-in RecyclerView.LayoutManager objects enable auto-measure by
default.
RecyclerView.LayoutManager no longer ignores some RecyclerView.LayoutParams settings, such as MATCH_PARENT in the scroll
direction.
Note: These lifted restrictions may cause unexpected behavior in your
layouts. Make sure you specify the correct layout
parameters.
Using com.android.support:recyclerview-v7:23.4.0 solves the problem of nested recyclerview not appearing in nested scroll view
When I put RecyclerView inside NestedScrollView then onBindViewHolder is calling for all row like say I have list which has size of 30 then onBindViewHolder is called for all 30 rows at one time even without scrolling
RecyclerView list;
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
list.setLayoutManager(layoutManager);
layoutManager.setAutoMeasureEnabled(true);
list.setNestedScrollingEnabled(false);
list.addItemDecoration(new VerticalSpaceItemDecoration(5));
list.setAdapter(adapter);
my xml is
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:scrollbars="none"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/grey">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_views"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/info"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:textAlignment="center"
android:visibility="visible"
/>
but if I remove NestedScrollView it's working properly.
I'm going to assume that since your are using appbar_scrolling_view_behavior you are trying to do something with AppBarLayout.
If so, you can use RecyclerView as a direct child of CoordinatorLayout and have support for AppBarLayout scrolling without nesting RecyclerView inside of NestedScrollView.
Try this: RecyclerView inside CoordinatorLayout (with AppBarLayout and CollapsingToolbarLayout):
<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:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#55FF00FF"
app:layout_collapseMode="none"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
And in your Activity or CustomView:
RecyclerView list;
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
list.setLayoutManager(layoutManager);
list.addItemDecoration(new VerticalSpaceItemDecoration(5));
list.setAdapter(adapter);
But you set android:layout_height for NestedScrollView to wrap_content - here, it's zero by default (because there no content for him at the moment of the declaration). Next, for RecyclerView you set android:layout_height to match_parent - which is at the moment is 0. Thus, all your items have 0 height.
Thus, you have such situation.
Solution: use solution above from #dkarmazi https://stackoverflow.com/a/37558761/3546306 or try to change parameter android:layout_height values.
It's right.Because you are using a ScrollView.ScrollView is not recyclable like RecyclerView or ListView.It will show all view contains these out of screen in one time.You should use a other layout instead.
I faced the same issue. After a bit of research fount the solution.
You need to make sure your recyclerview height is fixed by setting it to MATCH_PARENT. Or if its in a contraint layout then set height to 0dp and set the required height constrains.
Then set recyclerview.setHasFixedSize to true.
The onBindViewHolder will start getting called after this.