How to use RecyclerView inside NestedScrollView? - android

How to use RecyclerView inside NestedScrollView?
RecyclerView content is not visible after setting adapter.
UPDATE layout code updated.
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/keyline_1">
</RelativeLayout>
<View
android:id="#+id/separator"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#e5e5e5" />
<android.support.v7.widget.RecyclerView
android:id="#+id/conversation"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>

Replace your recyclerView with,
<android.support.v7.widget.RecyclerView
android:id="#+id/conversation"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
here,
app:layout_behavior="#string/appbar_scrolling_view_behavior"
will manage the rest of things.
One more thing, no need to put your recyclerView inside NestedScrollView

You need to use support library 23.2.0 (or) above
and RecyclerView height will be wrap_content.
recyclerView.setNestedScrollingEnabled(false)
But by doing this the recycler pattern doesn't work. (i.e all the views will be loaded at once because wrap_content needs the height of complete RecyclerView so it will draw all child Views at once. No view will be recycled). Try not to use this pattern unless it is really required. Try to use viewType and add all other views that need to scroll to RecyclerView rather than using RecyclerView in Scrollview. The performance impact will be very high.
To make it simple "it just acts as LinearLayout with all the child views"

UPDATE 1
Since Android Support Library 23.2.0 there were added method setAutoMeasureEnabled(true) for LayoutManagers. It makes RecyclerView to wrap it's content and works like a charm.
http://android-developers.blogspot.ru/2016/02/android-support-library-232.html
So just add something like this:
LayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setAutoMeasureEnabled(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setNestedScrollingEnabled(false);
UPDATE 2
Since 27.1.0 setAutoMeasureEnabled is deprecated, so you should provide custom implementation of LayoutManager with overridden method isAutoMeasureEnabled()
But after many cases of usage RecyclerView I strongly recommend not to use it in wrapping mode, cause this is not what it is intended for. Try to refactor whole your layout using normal single RecyclerView with several items' types. Or use approach with LinearLayout that I described below as last resort
Old answer (not recommended)
You can use RecyclerView inside NestedScrollView.
First of all you should implement your own custom LinearLayoutManager, it makes your RecyclerView to wrap its content.
For example:
public class WrappingLinearLayoutManager extends LinearLayoutManager
{
public WrappingLinearLayoutManager(Context context) {
super(context);
}
private int[] mMeasuredDimension = new int[2];
#Override
public boolean canScrollVertically() {
return false;
}
#Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
int widthSpec, int heightSpec) {
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec);
int width = 0;
int height = 0;
for (int i = 0; i < getItemCount(); i++) {
if (getOrientation() == HORIZONTAL) {
measureScrapChild(recycler, i,
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
heightSpec,
mMeasuredDimension);
width = width + mMeasuredDimension[0];
if (i == 0) {
height = mMeasuredDimension[1];
}
} else {
measureScrapChild(recycler, i,
widthSpec,
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
height = height + mMeasuredDimension[1];
if (i == 0) {
width = mMeasuredDimension[0];
}
}
}
switch (widthMode) {
case View.MeasureSpec.EXACTLY:
width = widthSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
switch (heightMode) {
case View.MeasureSpec.EXACTLY:
height = heightSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
setMeasuredDimension(width, height);
}
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
int heightSpec, int[] measuredDimension) {
View view = recycler.getViewForPosition(position);
if (view.getVisibility() == View.GONE) {
measuredDimension[0] = 0;
measuredDimension[1] = 0;
return;
}
// For adding Item Decor Insets to view
super.measureChildWithMargins(view, 0, 0);
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
int childWidthSpec = ViewGroup.getChildMeasureSpec(
widthSpec,
getPaddingLeft() + getPaddingRight() + getDecoratedLeft(view) + getDecoratedRight(view),
p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(
heightSpec,
getPaddingTop() + getPaddingBottom() + getDecoratedTop(view) + getDecoratedBottom(view),
p.height);
view.measure(childWidthSpec, childHeightSpec);
// Get decorated measurements
measuredDimension[0] = getDecoratedMeasuredWidth(view) + p.leftMargin + p.rightMargin;
measuredDimension[1] = getDecoratedMeasuredHeight(view) + p.bottomMargin + p.topMargin;
recycler.recycleView(view);
}
}
After that use this LayoutManager for your RecyclerView
recyclerView.setLayoutManager(new WrappingLinearLayoutManager(getContext()));
But you also should call those two methods:
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);
Here setNestedScrollingEnabled(false) disable scrolling for RecyclerView, so it doesn't intercept scrolling event from NestedScrollView. And setHasFixedSize(false) determine that changes in adapter content can change the size of the RecyclerView
Important note: This solution is little buggy in some cases and has problems with perfomance, so if you have a lot of items in your RecyclerView I'd recommend to use custom LinearLayout-based implementation of list view, create analogue of Adapter for it and make it behave like ListView or RecyclerView

You can use android:fillViewport="true" to make NestedScrollView measure the RecyclerView. The RecyclerView will fill the remaining height. so if you want to scroll the NestScrollView, you can set the RecyclerView's minHeight.

Simply adding recyclerView.setNestedScrollingEnabled(false); before setAdapter itself worked for me. I didn't add app:layout_behavior="#string/appbar_scrolling_view_behavior" anywhere & didn't set any custom layout manager
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:text="Some Text..."
android:padding="15dp" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:padding="15dp"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Quick Links"
android:textColor="#color/black"
android:textStyle="bold"
android:textAllCaps="true"
android:paddingLeft="20dp"
android:drawableLeft="#drawable/ic_trending_up_black_24dp"
android:drawablePadding="10dp"
android:layout_marginBottom="10dp"
android:textSize="16sp"/>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#efefef"/>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>

This is what working for me
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</android.support.v4.widget.NestedScrollView>

For androidx it's called androidx.core.widget.NestedScrollView - and it scrolls alike butter with properties isScrollContainer and measureAllChildren enabled:
<!-- Scrolling Content -->
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:isScrollContainer="true"
android:measureAllChildren="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fastScrollEnabled="true"
android:scrollbarStyle="insideInset"
android:scrollbars="vertical"
android:splitMotionEvents="false"
android:verticalScrollbarPosition="right"/>
</androidx.core.widget.NestedScrollView>

There is a simple and testing code u may check
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.NestedScrollView>

I used RecyclerView inside a NestedScrollView and it worked for me. The only gotcha I had to keep in mind was that a NestedScrollView takes only one child view. So in my case I used of LienearLayout viewgroup which was housing my RecyclerView plus a number of other views that I needed.
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.
So to solve that problem, I had to disable the scroll functionality of my RecyclerView with this method movieListNewRecyclerView.setNestedScrollingEnabled(false);
You can checkout my Instagram for a short video of what I actually did. This is my instagram handle ofelix03

Try to use this library - https://github.com/serso/android-linear-layout-manager.
LayoutManager of the library makes RecyclerView wraps its contents. In this case RecyclerView will be "as big as inner views", so it will not have a scrollbars and user will use scrolling abilities of NestedScrollView. Therefore, it will not be ambiguous like "scrollable inside scrollable".

Here is the code that I'm using to avoid scrolling issues:
mRecyclerView = (RecyclerView) view.findViewById(android.R.id.list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.getLayoutManager().setAutoMeasureEnabled(true);
mRecyclerView.setNestedScrollingEnabled(false);
mRecyclerView.setHasFixedSize(false);

I have Viewpager and RecyclerView inside the NestedScrollView. After adding below lines
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);
I solved slow scroll and scroll lag issue.

if you want to use RecyclerView in NestedScrollView this is a simple tricky, just set :
RecyclerView
recyclerView.setHasFixedSize(false) (java/kt)
android:nestedScrollingEnabled="false"
android:layout_height="wrap_content"
android:overScrollMode="never"
NestedScrollView
android:fillViewport="true"
this is work for me, and you can use many RecyclerView in NestedScrollView with this too.

If you are using RecyclerView-23.2.1 or later. Following solution will work just fine:
In your layout add RecyclerView like this:
<android.support.v7.widget.RecyclerView
android:id="#+id/review_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical" />
And in your java file:
RecyclerView mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager=new LinearLayoutManager(getContext());
layoutManager.setAutoMeasureEnabled(true);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setAdapter(new YourListAdapter(getContext()));
Here layoutManager.setAutoMeasureEnabled(true); will do the trick.
Check out this issue and this developer blog for more information.

If you are using RecyclerView ScrollListener inside NestedScrollView, addOnScrollListener listener not working properly if you are used both.
Use this code.
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
......
}
});
this code working fine RecyclerView ScrollListener inside NestedScrollView.
thanks

There are a lot of good answers. The key is that you must set nestedScrollingEnabled to false. As mentioned above you can do it in java code:
mRecyclerView.setNestedScrollingEnabled(false);
But also you have an opportunity to set the same property in xml code (android:nestedScrollingEnabled="false"):
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:nestedScrollingEnabled="false"
android:layout_width="match_parent"
android:layout_height="match_parent" />

You can't use a recycler view within a nested scroll view. It's not intended to contain further scrollable views but it's because it's a child of a scrolling layout itself that you need the nested scrolling view. I had the same issue but in the end I moved my textview to be a headerview within the recyclerview, made the recyclerview a direct child of the coordinator layout and deleted the nested scroll view. Then all my problems were gone.

One solution to keep the recycling feature of the recyclerview and avoiding the recyclerview to load all your data is setting a fix height in the recyclerview itself. By doing this the recyclerview is limited only to load as much as its height can show the user thus recycling its element if ever you scroll to the bottom/top.

do not use recyclerView inside NestedScrollView. it may cause cascading problems!
I suggest using ItemViewTypes in RecyclerView for handling multiple kinds of views.
just add a RecyclerView with match_parent width and height. then in your recyclerViewAdapter override getItemViewType and use position for handling what layout to be inflated. after that you can handle your view holder by using onBindViewHolder method.
https://stacklearn.ir

You can use my sample code
<?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"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:id="#+id/fl_all_brand"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".view.fragment.AllBrandFragment">
<androidx.core.widget.NestedScrollView
android:id="#+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:id="#+id/fl_all_brand1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--<include layout="#layout/content_home" />-->
<TextView
android:id="#+id/tv_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="#dimen/_15sdp"
android:layout_marginTop="#dimen/_20sdp"
android:fontFamily="#font/lexend_semibold"
android:text="#string/DISPLAY_LIGHTS"
android:textColor="#color/gray_scale_placehold"
android:textSize="#dimen/_16ssp" />
<LinearLayout
android:id="#+id/recyclerLayout"
android:layout_width="match_parent"
android:layout_height="#dimen/_280sdp">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerviewobj"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="#dimen/_10sdp"
android:layout_marginTop="#dimen/_20sdp"
android:layout_marginEnd="#dimen/_10sdp"
android:orientation="horizontal"
android:nestedScrollingEnabled="false"
android:layout_marginBottom="#dimen/_20sdp"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
/>
</LinearLayout>
<TextView
android:id="#+id/notfound"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="#dimen/_15sdp"
android:layout_marginTop="#dimen/_20sdp"
android:layout_marginBottom="#dimen/_20sdp"
android:fontFamily="#font/lexend_semibold"
android:text="#string/DISPLAY_LIGHTS"
android:gravity="center"
android:visibility="gone"
android:textColor="?attr/hintTextColors"
android:textSize="#dimen/_12ssp" />
<TextView
android:id="#+id/recommendTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/addDeviceLayout"
android:layout_below="#+id/recyclerviewobj"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_7sdp"
android:fontFamily="#font/lexend_semibold"
android:text="#string/RECOMMENDATION"
android:textColor="#color/gray_scale_placehold"
android:textSize="#dimen/_16ssp" />
<LinearLayout
android:id="#+id/addDeviceLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/createRoomLayout"
android:layout_marginTop="#dimen/_14sdp"
android:background="?attr/buttonTextColor"
android:orientation="vertical"
tools:visibility="visible">
<ImageView
android:id="#+id/addBtn"
android:layout_width="#dimen/_28sdp"
android:layout_height="#dimen/_28sdp"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_8sdp"
android:src="#drawable/ic_thermostates_icon"
app:tint="?attr/colorPrimaryDark" />
<TextView
android:id="#+id/addDevice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_5sdp"
android:fontFamily="#font/lexend_bold"
android:text="#string/PROGRAM_DISPLAY_SENSOR_PLUGS"
android:textColor="?attr/colorPrimaryDark"
android:textSize="#dimen/_12ssp" />
<TextView
android:id="#+id/summry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_8sdp"
android:layout_marginBottom="#dimen/_6sdp"
android:fontFamily="#font/lexend_medium"
android:text="#string/DISPLAY_SENSOR_SUB_TITLE"
android:textColor="?attr/secondaryTextColor"
android:textSize="#dimen/_9ssp" />
<RelativeLayout
android:id="#+id/container3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_6sdp"
android:layout_marginTop="#dimen/_6sdp"
android:layout_marginBottom="#dimen/_10sdp">
<TextView
android:id="#+id/get_started"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="#dimen/_10sdp"
android:fontFamily="#font/lexend_semibold"
android:text="#string/RECOMMENDED_GROUP"
android:textAllCaps="true"
android:textSize="#dimen/_9ssp" />
<ImageView
android:id="#+id/forward_arrow"
android:layout_width="#dimen/_16sdp"
android:layout_height="#dimen/_16sdp"
android:layout_alignParentEnd="true"
android:layout_marginRight="#dimen/_20sdp"
android:src="#drawable/ic_forward_arrow"
app:tint="?attr/colorPrimary" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:id="#+id/createRoomLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginTop="#dimen/_9sdp"
android:layout_marginBottom="#dimen/_20sdp"
android:background="?attr/buttonTextColor"
android:orientation="vertical"
tools:visibility="visible">
<ImageView
android:id="#+id/addBtnRoom"
android:layout_width="#dimen/_28sdp"
android:layout_height="#dimen/_28sdp"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_8sdp"
android:src="#drawable/rgb_light_new"
app:tint="?attr/colorPrimaryDark" />
<TextView
android:id="#+id/addRooms"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_5sdp"
android:fontFamily="#font/lexend_bold"
android:text="#string/DISPLAY_RGBW"
android:textColor="?attr/colorPrimaryDark"
android:textSize="#dimen/_12ssp" />
<TextView
android:id="#+id/summry1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_8sdp"
android:layout_marginBottom="#dimen/_6sdp"
android:fontFamily="#font/lexend_medium"
android:text="#string/PROGRAM_DISPLAY_RGB_MSG"
android:textColor="?attr/secondaryTextColor"
android:textSize="#dimen/_9ssp" />
<RelativeLayout
android:id="#+id/container99"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_6sdp"
android:layout_marginTop="#dimen/_6sdp"
android:layout_marginBottom="#dimen/_10sdp">
<TextView
android:id="#+id/get_started_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="#dimen/_10sdp"
android:fontFamily="#font/lexend_semibold"
android:text="#string/RECOMMENDED_GROUP"
android:textAllCaps="true"
android:textSize="#dimen/_9ssp" />
<ImageView
android:id="#+id/forward_arrow1"
android:layout_width="#dimen/_16sdp"
android:layout_height="#dimen/_16sdp"
android:layout_alignParentEnd="true"
android:layout_marginRight="#dimen/_20sdp"
android:src="#drawable/ic_forward_arrow"
app:tint="?attr/colorPrimary" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</layout>
here use this property of recyclerview
app:layout_behavior="#string/appbar_scrolling_view_behavior"
and turned off recyclerview nested scrolling like this
android:nestedScrollingEnabled="false"

I had to implement CoordinatorLayout with toolbar scrolling and it just took me all the day messing around this. I've got it working by removing NestedScrollView at all. So I'm just using RelativeLayout at the root.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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.support.v7.widget.RecyclerView
android:id="#+id/rv_nearby"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</RelativeLayout>

nestedScrollView.setNestedScrollingEnabled(true);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//...
}
});
<androidx.core.widget.NestedScrollView
android:id="#+id/nested"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:layout_below="#id/appBarLayout_orders"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout ...
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>

In my case, this is what works for me
Put android:fillViewport="true" inside NestedScrollView.
Make the height of RecyclerView to wrap_content, i.e android:layout_height="wrap_content"
Add this in RecyclerView android:nestedScrollingEnabled="false"
OR
Programmatically, in your Kotlin class
recyclerView.isNestedScrollingEnabled = false
mRecyclerView.setHasFixedSize(false)

For my case the child of NestedScrollview is ConstraintLayout. It is not working as expected i replaced it to LinearLayout. Maybe it helps someone.
<androidx.core.widget.NestedScrollView
android:id="#+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>

I have used this awesome extension (written in kotlin but can be also used in Java)
https://github.com/Widgetlabs/expedition-nestedscrollview
Basically you get the NestedRecyclerView inside any package lets say utils in your project, then just create your recyclerview like
<com.your_package.utils.NestedRecyclerView
android:id="#+id/rv_test"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Check this awesome article by Marc Knaup
https://medium.com/widgetlabs-engineering/scrollable-nestedscrollviews-inside-recyclerview-ca65050d828a

At least as far back as Material Components 1.3.0-alpha03, it doesn't matter if the RecyclerView is nested (in something other than a ScrollView or NestedScrollView). Just put app:layout_behavior="#string/appbar_scrolling_view_behavior" on its top level parent that's a sibling of the AppBarLayout in the CoordinatorLayout.
This has been working for me when using a single Activity architecture with Jetpack Naviagation, where all Fragments are sharing the same AppBar from the Activity's layout. I make the FragmentContainer the direct child of the CoordinatorLayout that also contains the AppBarLayout, like below. The RecyclerViews in the various fragments are scrolling normally and the AppBar folds away and reappears as expected.
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="#+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
app:defaultNavHost="true"
app:navGraph="#navigation/mobile_navigation"/>
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:layout_scrollFlags="scroll|enterAlways|snap" />
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
liftOnScroll (used to for app bars to look like they have zero elevation when at the top of the page) works if each fragment passes the ID of its RecyclerView to AppBarLayout.liftOnScrollTargetViewId in Fragment.onResume. Or pass 0 if the Fragment doesn't scroll.

RecyclerView with NestedScrollView
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />

Related

Two Vertical RecyclerView scrolling at the same time

I have two RecyclerView, both have a vertical orientation, I need to scroll one of them so that the second scrolls, that is, their scrolling is synchronous, I thought that it is possible to apply one LinearLayoutManager to these two RecyclerView and then it will be work, but in this log, the error LinearLayoutManager is already attached to a RecyclerView will be generated, so I don't know how to be, help me find a solution, I need two independent RecyclerView with different adapters, but which scroll synchronously, so do not write about GridLayoutManager, thanks.
xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_0"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:clipToPadding="false"
android:orientation="vertical"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:clipToPadding="false"
android:orientation="vertical"/>
</LinearLayout>
Cod
val RLM_0 = LinearLayoutManager(context)
rv_0.setHasFixedSize(false)
rv_0.isNestedScrollingEnabled = false
rv_0.layoutManager = RLM_0
adapter_0 = Adapter_0(itemTasks, requireActivity())
rv_0.adapter = adapter_0
val RLM_1 = LinearLayoutManager(context)
rv_1.setHasFixedSize(false)
rv_1.isNestedScrollingEnabled = false
rv_1.layoutManager = RLM_1
adapter_1 = Adapter_1(itemTasks, requireActivity())
rv_1.adapter = adapter_1
Solution 1:
Check is: Sync scrolling of multiple RecyclerViews
Solution 2:
There is an other way to do so, the idea is to disable scroll for each recycler view and surround them with a scroll view.
This is how you can implement it:
binding.recyclerViewOne.setOnTouchListener((v, event) -> true);
binding.recyclerViewTwo.setOnTouchListener((v, event) -> true);
And for the layout:
<ScrollView
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</LinearLayout>
</ScrollView>

recyclerview inside coordinatorlayout doesn't work properly [duplicate]

How to use RecyclerView inside NestedScrollView?
RecyclerView content is not visible after setting adapter.
UPDATE layout code updated.
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/keyline_1">
</RelativeLayout>
<View
android:id="#+id/separator"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#e5e5e5" />
<android.support.v7.widget.RecyclerView
android:id="#+id/conversation"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
Replace your recyclerView with,
<android.support.v7.widget.RecyclerView
android:id="#+id/conversation"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
here,
app:layout_behavior="#string/appbar_scrolling_view_behavior"
will manage the rest of things.
One more thing, no need to put your recyclerView inside NestedScrollView
You need to use support library 23.2.0 (or) above
and RecyclerView height will be wrap_content.
recyclerView.setNestedScrollingEnabled(false)
But by doing this the recycler pattern doesn't work. (i.e all the views will be loaded at once because wrap_content needs the height of complete RecyclerView so it will draw all child Views at once. No view will be recycled). Try not to use this pattern unless it is really required. Try to use viewType and add all other views that need to scroll to RecyclerView rather than using RecyclerView in Scrollview. The performance impact will be very high.
To make it simple "it just acts as LinearLayout with all the child views"
UPDATE 1
Since Android Support Library 23.2.0 there were added method setAutoMeasureEnabled(true) for LayoutManagers. It makes RecyclerView to wrap it's content and works like a charm.
http://android-developers.blogspot.ru/2016/02/android-support-library-232.html
So just add something like this:
LayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setAutoMeasureEnabled(true);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setNestedScrollingEnabled(false);
UPDATE 2
Since 27.1.0 setAutoMeasureEnabled is deprecated, so you should provide custom implementation of LayoutManager with overridden method isAutoMeasureEnabled()
But after many cases of usage RecyclerView I strongly recommend not to use it in wrapping mode, cause this is not what it is intended for. Try to refactor whole your layout using normal single RecyclerView with several items' types. Or use approach with LinearLayout that I described below as last resort
Old answer (not recommended)
You can use RecyclerView inside NestedScrollView.
First of all you should implement your own custom LinearLayoutManager, it makes your RecyclerView to wrap its content.
For example:
public class WrappingLinearLayoutManager extends LinearLayoutManager
{
public WrappingLinearLayoutManager(Context context) {
super(context);
}
private int[] mMeasuredDimension = new int[2];
#Override
public boolean canScrollVertically() {
return false;
}
#Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
int widthSpec, int heightSpec) {
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec);
int width = 0;
int height = 0;
for (int i = 0; i < getItemCount(); i++) {
if (getOrientation() == HORIZONTAL) {
measureScrapChild(recycler, i,
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
heightSpec,
mMeasuredDimension);
width = width + mMeasuredDimension[0];
if (i == 0) {
height = mMeasuredDimension[1];
}
} else {
measureScrapChild(recycler, i,
widthSpec,
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
height = height + mMeasuredDimension[1];
if (i == 0) {
width = mMeasuredDimension[0];
}
}
}
switch (widthMode) {
case View.MeasureSpec.EXACTLY:
width = widthSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
switch (heightMode) {
case View.MeasureSpec.EXACTLY:
height = heightSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
setMeasuredDimension(width, height);
}
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
int heightSpec, int[] measuredDimension) {
View view = recycler.getViewForPosition(position);
if (view.getVisibility() == View.GONE) {
measuredDimension[0] = 0;
measuredDimension[1] = 0;
return;
}
// For adding Item Decor Insets to view
super.measureChildWithMargins(view, 0, 0);
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
int childWidthSpec = ViewGroup.getChildMeasureSpec(
widthSpec,
getPaddingLeft() + getPaddingRight() + getDecoratedLeft(view) + getDecoratedRight(view),
p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(
heightSpec,
getPaddingTop() + getPaddingBottom() + getDecoratedTop(view) + getDecoratedBottom(view),
p.height);
view.measure(childWidthSpec, childHeightSpec);
// Get decorated measurements
measuredDimension[0] = getDecoratedMeasuredWidth(view) + p.leftMargin + p.rightMargin;
measuredDimension[1] = getDecoratedMeasuredHeight(view) + p.bottomMargin + p.topMargin;
recycler.recycleView(view);
}
}
After that use this LayoutManager for your RecyclerView
recyclerView.setLayoutManager(new WrappingLinearLayoutManager(getContext()));
But you also should call those two methods:
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);
Here setNestedScrollingEnabled(false) disable scrolling for RecyclerView, so it doesn't intercept scrolling event from NestedScrollView. And setHasFixedSize(false) determine that changes in adapter content can change the size of the RecyclerView
Important note: This solution is little buggy in some cases and has problems with perfomance, so if you have a lot of items in your RecyclerView I'd recommend to use custom LinearLayout-based implementation of list view, create analogue of Adapter for it and make it behave like ListView or RecyclerView
You can use android:fillViewport="true" to make NestedScrollView measure the RecyclerView. The RecyclerView will fill the remaining height. so if you want to scroll the NestScrollView, you can set the RecyclerView's minHeight.
Simply adding recyclerView.setNestedScrollingEnabled(false); before setAdapter itself worked for me. I didn't add app:layout_behavior="#string/appbar_scrolling_view_behavior" anywhere & didn't set any custom layout manager
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:text="Some Text..."
android:padding="15dp" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:padding="15dp"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Quick Links"
android:textColor="#color/black"
android:textStyle="bold"
android:textAllCaps="true"
android:paddingLeft="20dp"
android:drawableLeft="#drawable/ic_trending_up_black_24dp"
android:drawablePadding="10dp"
android:layout_marginBottom="10dp"
android:textSize="16sp"/>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#efefef"/>
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
This is what working for me
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="#string/appbar_scrolling_view_behavior"/>
</android.support.v4.widget.NestedScrollView>
For androidx it's called androidx.core.widget.NestedScrollView - and it scrolls alike butter with properties isScrollContainer and measureAllChildren enabled:
<!-- Scrolling Content -->
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:isScrollContainer="true"
android:measureAllChildren="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fastScrollEnabled="true"
android:scrollbarStyle="insideInset"
android:scrollbars="vertical"
android:splitMotionEvents="false"
android:verticalScrollbarPosition="right"/>
</androidx.core.widget.NestedScrollView>
There is a simple and testing code u may check
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.NestedScrollView>
I used RecyclerView inside a NestedScrollView and it worked for me. The only gotcha I had to keep in mind was that a NestedScrollView takes only one child view. So in my case I used of LienearLayout viewgroup which was housing my RecyclerView plus a number of other views that I needed.
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.
So to solve that problem, I had to disable the scroll functionality of my RecyclerView with this method movieListNewRecyclerView.setNestedScrollingEnabled(false);
You can checkout my Instagram for a short video of what I actually did. This is my instagram handle ofelix03
Try to use this library - https://github.com/serso/android-linear-layout-manager.
LayoutManager of the library makes RecyclerView wraps its contents. In this case RecyclerView will be "as big as inner views", so it will not have a scrollbars and user will use scrolling abilities of NestedScrollView. Therefore, it will not be ambiguous like "scrollable inside scrollable".
Here is the code that I'm using to avoid scrolling issues:
mRecyclerView = (RecyclerView) view.findViewById(android.R.id.list);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
mRecyclerView.getLayoutManager().setAutoMeasureEnabled(true);
mRecyclerView.setNestedScrollingEnabled(false);
mRecyclerView.setHasFixedSize(false);
I have Viewpager and RecyclerView inside the NestedScrollView. After adding below lines
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(false);
I solved slow scroll and scroll lag issue.
if you want to use RecyclerView in NestedScrollView this is a simple tricky, just set :
RecyclerView
recyclerView.setHasFixedSize(false) (java/kt)
android:nestedScrollingEnabled="false"
android:layout_height="wrap_content"
android:overScrollMode="never"
NestedScrollView
android:fillViewport="true"
this is work for me, and you can use many RecyclerView in NestedScrollView with this too.
If you are using RecyclerView-23.2.1 or later. Following solution will work just fine:
In your layout add RecyclerView like this:
<android.support.v7.widget.RecyclerView
android:id="#+id/review_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="vertical" />
And in your java file:
RecyclerView mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager=new LinearLayoutManager(getContext());
layoutManager.setAutoMeasureEnabled(true);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setAdapter(new YourListAdapter(getContext()));
Here layoutManager.setAutoMeasureEnabled(true); will do the trick.
Check out this issue and this developer blog for more information.
If you are using RecyclerView ScrollListener inside NestedScrollView, addOnScrollListener listener not working properly if you are used both.
Use this code.
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
......
}
});
this code working fine RecyclerView ScrollListener inside NestedScrollView.
thanks
There are a lot of good answers. The key is that you must set nestedScrollingEnabled to false. As mentioned above you can do it in java code:
mRecyclerView.setNestedScrollingEnabled(false);
But also you have an opportunity to set the same property in xml code (android:nestedScrollingEnabled="false"):
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:nestedScrollingEnabled="false"
android:layout_width="match_parent"
android:layout_height="match_parent" />
You can't use a recycler view within a nested scroll view. It's not intended to contain further scrollable views but it's because it's a child of a scrolling layout itself that you need the nested scrolling view. I had the same issue but in the end I moved my textview to be a headerview within the recyclerview, made the recyclerview a direct child of the coordinator layout and deleted the nested scroll view. Then all my problems were gone.
One solution to keep the recycling feature of the recyclerview and avoiding the recyclerview to load all your data is setting a fix height in the recyclerview itself. By doing this the recyclerview is limited only to load as much as its height can show the user thus recycling its element if ever you scroll to the bottom/top.
do not use recyclerView inside NestedScrollView. it may cause cascading problems!
I suggest using ItemViewTypes in RecyclerView for handling multiple kinds of views.
just add a RecyclerView with match_parent width and height. then in your recyclerViewAdapter override getItemViewType and use position for handling what layout to be inflated. after that you can handle your view holder by using onBindViewHolder method.
https://stacklearn.ir
You can use my sample code
<?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"
xmlns:tools="http://schemas.android.com/tools">
<LinearLayout
android:id="#+id/fl_all_brand"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".view.fragment.AllBrandFragment">
<androidx.core.widget.NestedScrollView
android:id="#+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:id="#+id/fl_all_brand1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--<include layout="#layout/content_home" />-->
<TextView
android:id="#+id/tv_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="#dimen/_15sdp"
android:layout_marginTop="#dimen/_20sdp"
android:fontFamily="#font/lexend_semibold"
android:text="#string/DISPLAY_LIGHTS"
android:textColor="#color/gray_scale_placehold"
android:textSize="#dimen/_16ssp" />
<LinearLayout
android:id="#+id/recyclerLayout"
android:layout_width="match_parent"
android:layout_height="#dimen/_280sdp">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerviewobj"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="#dimen/_10sdp"
android:layout_marginTop="#dimen/_20sdp"
android:layout_marginEnd="#dimen/_10sdp"
android:orientation="horizontal"
android:nestedScrollingEnabled="false"
android:layout_marginBottom="#dimen/_20sdp"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
/>
</LinearLayout>
<TextView
android:id="#+id/notfound"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="#dimen/_15sdp"
android:layout_marginTop="#dimen/_20sdp"
android:layout_marginBottom="#dimen/_20sdp"
android:fontFamily="#font/lexend_semibold"
android:text="#string/DISPLAY_LIGHTS"
android:gravity="center"
android:visibility="gone"
android:textColor="?attr/hintTextColors"
android:textSize="#dimen/_12ssp" />
<TextView
android:id="#+id/recommendTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/addDeviceLayout"
android:layout_below="#+id/recyclerviewobj"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_7sdp"
android:fontFamily="#font/lexend_semibold"
android:text="#string/RECOMMENDATION"
android:textColor="#color/gray_scale_placehold"
android:textSize="#dimen/_16ssp" />
<LinearLayout
android:id="#+id/addDeviceLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/createRoomLayout"
android:layout_marginTop="#dimen/_14sdp"
android:background="?attr/buttonTextColor"
android:orientation="vertical"
tools:visibility="visible">
<ImageView
android:id="#+id/addBtn"
android:layout_width="#dimen/_28sdp"
android:layout_height="#dimen/_28sdp"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_8sdp"
android:src="#drawable/ic_thermostates_icon"
app:tint="?attr/colorPrimaryDark" />
<TextView
android:id="#+id/addDevice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_5sdp"
android:fontFamily="#font/lexend_bold"
android:text="#string/PROGRAM_DISPLAY_SENSOR_PLUGS"
android:textColor="?attr/colorPrimaryDark"
android:textSize="#dimen/_12ssp" />
<TextView
android:id="#+id/summry"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_8sdp"
android:layout_marginBottom="#dimen/_6sdp"
android:fontFamily="#font/lexend_medium"
android:text="#string/DISPLAY_SENSOR_SUB_TITLE"
android:textColor="?attr/secondaryTextColor"
android:textSize="#dimen/_9ssp" />
<RelativeLayout
android:id="#+id/container3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_6sdp"
android:layout_marginTop="#dimen/_6sdp"
android:layout_marginBottom="#dimen/_10sdp">
<TextView
android:id="#+id/get_started"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="#dimen/_10sdp"
android:fontFamily="#font/lexend_semibold"
android:text="#string/RECOMMENDED_GROUP"
android:textAllCaps="true"
android:textSize="#dimen/_9ssp" />
<ImageView
android:id="#+id/forward_arrow"
android:layout_width="#dimen/_16sdp"
android:layout_height="#dimen/_16sdp"
android:layout_alignParentEnd="true"
android:layout_marginRight="#dimen/_20sdp"
android:src="#drawable/ic_forward_arrow"
app:tint="?attr/colorPrimary" />
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:id="#+id/createRoomLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginTop="#dimen/_9sdp"
android:layout_marginBottom="#dimen/_20sdp"
android:background="?attr/buttonTextColor"
android:orientation="vertical"
tools:visibility="visible">
<ImageView
android:id="#+id/addBtnRoom"
android:layout_width="#dimen/_28sdp"
android:layout_height="#dimen/_28sdp"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_8sdp"
android:src="#drawable/rgb_light_new"
app:tint="?attr/colorPrimaryDark" />
<TextView
android:id="#+id/addRooms"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_5sdp"
android:fontFamily="#font/lexend_bold"
android:text="#string/DISPLAY_RGBW"
android:textColor="?attr/colorPrimaryDark"
android:textSize="#dimen/_12ssp" />
<TextView
android:id="#+id/summry1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_16sdp"
android:layout_marginTop="#dimen/_8sdp"
android:layout_marginBottom="#dimen/_6sdp"
android:fontFamily="#font/lexend_medium"
android:text="#string/PROGRAM_DISPLAY_RGB_MSG"
android:textColor="?attr/secondaryTextColor"
android:textSize="#dimen/_9ssp" />
<RelativeLayout
android:id="#+id/container99"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/_6sdp"
android:layout_marginTop="#dimen/_6sdp"
android:layout_marginBottom="#dimen/_10sdp">
<TextView
android:id="#+id/get_started_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="#dimen/_10sdp"
android:fontFamily="#font/lexend_semibold"
android:text="#string/RECOMMENDED_GROUP"
android:textAllCaps="true"
android:textSize="#dimen/_9ssp" />
<ImageView
android:id="#+id/forward_arrow1"
android:layout_width="#dimen/_16sdp"
android:layout_height="#dimen/_16sdp"
android:layout_alignParentEnd="true"
android:layout_marginRight="#dimen/_20sdp"
android:src="#drawable/ic_forward_arrow"
app:tint="?attr/colorPrimary" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>
</layout>
here use this property of recyclerview
app:layout_behavior="#string/appbar_scrolling_view_behavior"
and turned off recyclerview nested scrolling like this
android:nestedScrollingEnabled="false"
I had to implement CoordinatorLayout with toolbar scrolling and it just took me all the day messing around this. I've got it working by removing NestedScrollView at all. So I'm just using RelativeLayout at the root.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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.support.v7.widget.RecyclerView
android:id="#+id/rv_nearby"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
</RelativeLayout>
nestedScrollView.setNestedScrollingEnabled(true);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
//...
}
});
<androidx.core.widget.NestedScrollView
android:id="#+id/nested"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:layout_below="#id/appBarLayout_orders"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<androidx.constraintlayout.widget.ConstraintLayout ...
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
In my case, this is what works for me
Put android:fillViewport="true" inside NestedScrollView.
Make the height of RecyclerView to wrap_content, i.e android:layout_height="wrap_content"
Add this in RecyclerView android:nestedScrollingEnabled="false"
OR
Programmatically, in your Kotlin class
recyclerView.isNestedScrollingEnabled = false
mRecyclerView.setHasFixedSize(false)
For my case the child of NestedScrollview is ConstraintLayout. It is not working as expected i replaced it to LinearLayout. Maybe it helps someone.
<androidx.core.widget.NestedScrollView
android:id="#+id/nestedScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
I have used this awesome extension (written in kotlin but can be also used in Java)
https://github.com/Widgetlabs/expedition-nestedscrollview
Basically you get the NestedRecyclerView inside any package lets say utils in your project, then just create your recyclerview like
<com.your_package.utils.NestedRecyclerView
android:id="#+id/rv_test"
android:layout_width="match_parent"
android:layout_height="match_parent" />
Check this awesome article by Marc Knaup
https://medium.com/widgetlabs-engineering/scrollable-nestedscrollviews-inside-recyclerview-ca65050d828a
At least as far back as Material Components 1.3.0-alpha03, it doesn't matter if the RecyclerView is nested (in something other than a ScrollView or NestedScrollView). Just put app:layout_behavior="#string/appbar_scrolling_view_behavior" on its top level parent that's a sibling of the AppBarLayout in the CoordinatorLayout.
This has been working for me when using a single Activity architecture with Jetpack Naviagation, where all Fragments are sharing the same AppBar from the Activity's layout. I make the FragmentContainer the direct child of the CoordinatorLayout that also contains the AppBarLayout, like below. The RecyclerViews in the various fragments are scrolling normally and the AppBar folds away and reappears as expected.
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="#+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
app:defaultNavHost="true"
app:navGraph="#navigation/mobile_navigation"/>
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/appbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="true">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:layout_scrollFlags="scroll|enterAlways|snap" />
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
liftOnScroll (used to for app bars to look like they have zero elevation when at the top of the page) works if each fragment passes the ID of its RecyclerView to AppBarLayout.liftOnScrollTargetViewId in Fragment.onResume. Or pass 0 if the Fragment doesn't scroll.
RecyclerView with NestedScrollView
<android.support.v7.widget.RecyclerView
android:id="#+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />

Seekbar in recyclerview also moves recyclerview

Basically i have implemented recyclerview in nested scroll view which contains the arc seek bar in each item of recyclerview. So when i move seekbar recyclerview is also scrolling.
I tried using nestedscrollview and focusableInTouchMode option but did not worked.
device_list.apply {
device_list.layoutManager = GridLayoutManager(this#RoomActivity, 2)
device_list.adapter = DeviceAdapter()
}
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?android:attr/actionBarSize"
android:background="#color/colorWhite">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/device_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="#dimen/marginSemiGlobal"
android:layout_marginBottom="#dimen/marginSemiGlobal"
android:overScrollMode="never"
android:nestedScrollingEnabled="false"
android:scrollbars="none" />
</androidx.core.widget.NestedScrollView>
<com.marcinmoskala.arcseekbar.ArcSeekBar
app:roundEdges="true"
android:layout_width="match_parent"
android:layout_below="#+id/top_layout"
app:progressBackgroundColor="#color/colorProgressBackground"
app:progressBackgroundWidth="8dp"
app:progressColor="#color/colorProgress"
android:id="#+id/dimmer"
app:progressWidth="8dp"
android:layout_height="100dp"
app:thumb="#drawable/ic_progress_thumb"
android:layout_centerHorizontal="true" />
I tried setting setNestedScrollview to ViewCompact and also used focus in touch mode but output was same.

Increase the height of recyclerview dynamically on item add

Display pic
In my app, i want to increase the height of recycler view dynamically. As i add new item under complaints, the height of recycler view should increase. Is there a way to do it? Please help me with this. Thanks in advance.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="#+id/complaint_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/background_line"
android:padding="#dimen/layout_margin"
android:text="Complaints"
android:textColor="#color/textColorFullBlack" />
<LinearLayout
android:id="#+id/complaints_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="#dimen/layout_margin"
android:layout_weight="1">
<android.support.v7.widget.RecyclerView
android:id="#+id/complaint_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/layout_margin"
android:divider="#color/toolBarBackground"
android:groupIndicator="#android:color/transparent" />
</LinearLayout>
<TextView
android:id="#+id/instructions_text_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/background_line"
android:padding="#dimen/layout_margin"
android:text="Instructions"
android:textColor="#color/textColorFullBlack" />
<FrameLayout
android:id="#+id/instructions_container"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="#dimen/layout_margin"
android:layout_weight="1">
<android.support.v7.widget.RecyclerView
android:id="#+id/instructions_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/layout_margin"
android:divider="#color/toolBarBackground"
android:groupIndicator="#android:color/transparent" />
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#color/colorPrimary"
android:orientation="horizontal">
<in.palmpower.videocon.uicommon.widget.EditText
android:id="#+id/search_text_field"
style="#style/FormEditText"
android:layout_width="0dp"
android:layout_gravity="center_vertical"
android:layout_margin="#dimen/one_dp"
android:layout_weight="1"
android:background="#android:color/white"
android:inputType="textFilter"
android:padding="#dimen/search_edit_text_padding"
android:privateImeOptions="nm" />
<Button
android:id="#+id/add_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:background="?attr/selectableItemBackground"
android:contentDescription="#string/edittext_hint_search"
android:padding="#dimen/button_padding"
android:text="#string/add_button_string"
android:textColor="#color/textColorWhite" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
Got stuck on same issue, i was using RecyclerView with wrap_content inside LinearLayout, i change LinearLayout to RelativeLayout and it set RecyclerView Height Based On Children.
This will work for you
RecyclerView mRecyclerView
= (RecyclerView) findViewById(R.id.complaint_recycler_view);
int originalItemSize = iteList.size();
ViewGroup.LayoutParams params = mRecyclerView.getLayoutParams();
if (itemList.size() > originalItemSize ){
params.height = params.height + 100;
originalItemSize = itemList.size();
mRecyclerView.setLayoutParams(params);
}
i suggest you to put teh recyclerview in any other layout (Relative layout is preferable). Then change recyclerview's height/width as match parent to that layout and set teh parent layout's height/width as wrap content. it works for me
WRAP_CONTENT will not work if you want recyclerView to take part of screen.
If you want other content to be there below recyclerView, you can put recyclerView inside LinearLayout and use the following code to change the height dynamically.
I assume you are using a list(complaint_list) for storing complaints.Adjust the complaint_height accordingly
ViewGroup.LayoutParams params = mRecyclerView.getLayoutParams();
int complaint_height=400;
if (complaints_list.size() > 2) {
params.height = ((complaint_list.size() - 1) * 100) + complaint_height;
} else {
params.height = complaint_height+100;
}
mRecyclerView.setLayoutParams(params);

NestedScrollView scrolls to top on Recyclerview resized

I have a NestedScrollView containing a LinearLayout and a RecyclerView (both inside a RelativeLayout).
<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.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/scroll">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/lay_account">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:paddingTop="10dp"
android:id="#+id/lay_total"
android:paddingBottom="10dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/total"
android:id="#+id/lblTotal"
android:textSize="#dimen/text_medium"
android:layout_marginLeft="20dp"
android:textColor="#color/dark_eurakostheme_color"
android:textStyle="bold"/>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/txtTotalAmount"
android:textSize="#dimen/text_extra_extra_large"
android:gravity="center_horizontal"
android:textColor="#color/eurakostheme_color"/>
<ImageView
android:layout_width="#dimen/icon_extra_extra_large"
android:layout_height="match_parent"
android:id="#+id/imageView3"
android:src="#drawable/coin_eurakos"/>
</LinearLayout>
</LinearLayout>
<View
android:layout_width="fill_parent"
android:layout_height="1dp"
android:id="#+id/divisor"
android:background="#color/dividerColor"
android:layout_alignBottom="#+id/lay_total"/>
<android.support.v7.widget.RecyclerView
android:layout_below="#id/lay_total"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/rclBasketAmounts"
android:background="#android:color/white"
android:padding="10dp">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
After loading the data into the RecyclerView, I need to change it's height programmatically like this:
RelativeLayout.LayoutParams lay_params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
50 + ((int) (baskets.length * getResources().getDimension(R.dimen.list_height_small))));
lay_params.addRule(RelativeLayout.BELOW, lay_total.getId());
recyclerView.setLayoutParams(lay_params);
recyclerView.setAdapter(new ListBasketAmountAdapter(baskets));
The problem is when the data has finished loading the NestedScrollView scrolls automatically scrolls to the top of the RecyclerView, hiding the LinearLayout above it. Any ideas?
Thanks.
After several days I've found a solution to the problem. You just need to add the descendantFocusability in the first layout under the ScrollView like this:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/lay_account"
android:descendantFocusability="blocksDescendants">
The solution given by kevings14 works but it wasn't helpful in my case. I've a RecyclerView + a couple of EditText under NestedScrollView, when I added
android:descendantFocusability="blocksDescendants"
in main layout under scroll view. I was unable to focus EditText.
Then I came up with this solution, which worked for me.
<RelativeLayout
android:layout_width="match_parent"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_height="wrap_content">
In my case, I use multiple RecyclerView inside NestedScrollView. Then
it does not work for me. So my solution is, When my data update complete then I just scroll to top,
yourList.setAdapter(yourListAdapter);
scrollView.post(new Runnable() {
#Override
public void run() {
scrollView.fullScroll(ScrollView.FOCUS_UP);
//scrollView.scrollTo(0,0);
}
});
I had a nestedscrollview that would get scrolled up by itself. In the post run method of the recyclerview, I scrolled the nestedscrollview to (0,0) and all good.
rvComments.setAdapter(adapterComment);
rvComments.post(new Runnable() {
#Override
public void run() {
nestedScrollView.scrollTo(0, 0);
}
});

Categories

Resources