RecyclerView inside NestedScrollview not scrolling smoothly - android

When I'm scrolling down, the items above the RecyclerView does not scroll unless I start touching from the layout above, and it only scrolls down when I have reached the end of the RecyclerView.
<NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout>
<Some other items.../>
</LinearLayout>
<RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</NestedScrollView>
Note:
I actually use a fixed size for the RecyclerView, setting it via the code below:
float height_recyclerview = (ScreenUtil.getHeight(context) - (height_banner + height_bottom_navigation + height_create_post));
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, (int) height_recyclerview);
rv.setLayoutParams(layoutParams);
Why do I use fixed size if it works smoothly with wrap_content?
I will be displaying possibly thousands of items that may have
images, which will hurt performance if it does not actually do
recycling because of the issue that the RecyclerView is inside the
NestedScrollView
I have implemented an EndlessRecyclerViewScrollListener which has an
issue that it keeps loading more data from server continuously if
implemented with a RecyclerView that is within whatever scrollable
view, or if it is in a scrollable view, but does not have a fixed
height, even if you are not scrolling down.
I have tried the following:
set nested scrolling to false on the recycler view
try using scroll view instead of nested scroll view
a bunch of other code related to layouts and scrolling behaviors that others suggested which didn't work for me because I'm implementing it in a much more complicated layout and the fact that I use EndlessRecyclerViewScrollListener
What I want to fix?
I want to make the page scroll like a single page, not as a separate scrollable view.
Note that my recycler view has a fixed height that takes the entire screen's space meaning that its height is actually fit assuming that the linear layout above is not visible anymore if the user has scrolled down.
The ideal scenario is to make the scrollview scroll down first, to make the recycler view take the entire screen, so that the recyclerview will scroll however the user wants to.
Then the linearlayout above which should not be visible anymore if the recycler view has taken up all the space of the screen, should only show up if the recycler view has reached the top/first item, if the user keeps scrolling back up.

Read this.
Add app:layout_behavior="#string/appbar_scrolling_view_behavior" to your recycler xml.
<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" />

NestedScrollView Smooth Scrolling
recyclerView.isNestedScrollingEnabled = true
Do this programmatically
<androidx.core.widget.NestedScrollView 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="0dp"
android:fillViewport="true"
...

Related

Android Recyclerview in ScrollView

I know it is not a good approach, but I have a layout with similar structure:
ScrollView
RelativeLayout (with TabLayout,textViews, ImageViews etc)
RecyclerView
RelativeLayout (with textViews, ImageViews etc)
The recyclerView part is dynamic, so it may have 1 TextView with ImageView, but it can have max. 4-5 lines of elements.
This is working fine, but when there are more items in recyclerView, then that section starts to scroll.
That's what I want to disable.
My RecyclerView part:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerview2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
I added to the RecyclerView this line:
android:nestedScrollingEnabled="false"
So now the scrolling is disabled for that section, but now I don't see all items in RecyclerView.
How can I disable scrolling and keep the full height to see all the content there?

Recyclerview inside NestedScrollView - Scroll to bottom

I have a RecyclerView inside a NestedScrollView:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="#dimen/_100sdp">
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view_chat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="#dimen/_100sdp"
android:layout_marginLeft="#dimen/_30sdp"
android:layout_marginRight="#dimen/_30sdp"
android:background="#color/bright_grey"
></android.support.v7.widget.RecyclerView>
</android.support.v4.widget.NestedScrollView>
My RecyclerView is being filled with items in onCreate()
On a device you would see the first item of the RecyclerView on the very top und would have to scroll down the NestedScrollView in order to see the last item.
Since my items are chat message sorted by the time sent I need the NestedScrollView to be scrolled all the way down so users would see the latest chat message first without having to scroll in the first place.
Any ideas on this?
Given that your RecyclerView is the only child of your NestedScrollView, you would be better off removing the NestedScrollView altogether, and instead applying the fixed height to the RecyclerView. Something like this:
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view_chat"
android:layout_width="match_parent"
android:layout_height="#dimen/_100sdp"
android:layout_marginLeft="#dimen/_30sdp"
android:layout_marginRight="#dimen/_30sdp"
android:background="#color/bright_grey" />
Doing this allows you to have the RecyclerView itself manage scrolling, rather than the parent scroll view. And that allows you to leverage a property of LinearLayoutManager to achieve what you want.
Reverse layout -- setting this will "invert" your list; the first item in your adapter will appear at the bottom of the list, and the default scroll position of the RecyclerView will be to scroll all the way to the bottom.
https://developer.android.com/reference/android/support/v7/widget/LinearLayoutManager.html#setReverseLayout(boolean)
LinearLayoutManager lm = new LinearLayoutManager(this);
lm.setReverseLayout(true);
If you have the same issue and want to keep the NestedScrollView.
It will work like this.
Handler(Looper.getMainLooper()).postDelayed({
binding.nestedScrollView.smoothScrollTo(
0,
binding.recyclerview.measuredHeight,
500
)
// binding.nestedScrollView.scrollTo(0, binding.recyclerview.measuredHeight)
// binding.nestedScrollView.smoothScrollTo(0, binding.recyclerview.measuredHeight)
}, 50L)
For me, it didn't work without delay.

RecyclerView (horizontal) nested in BottomSheet preventing vertical scrolling

I have a RecyclerView using a LinearLayoutManager with HORIZONTAL orientation, nested inside a FrameLayout using the BottomSheet Behavior.
When attempting to drag vertically across the RecyclerView, the BottomSheet doesn't respond to the drag event. Presumably this is because vertical scrolling is disabled for a LayoutManager with horizontal orientation.
I've tried overriding LinearLayoutManager.canScrollVertically() and returning true. This sort of works.. If you drag vertically in a very careful manner, the BottomSheet will respond. As soon as any horizontal movement is involved however, the BottomSheet stops responding to vertical drag events.
I'm not sure if overriding canScrollVertically() is the right approach here - it certainly doesn't feel right from a UX point of view.
I've also noticed that if I use a ViewPager rather than a RecyclerView with a horizontally oriented LayoutManager, the BottomSheet responds to vertical swipe events as desired.
Is there some other method of LayoutManager, RecyclerView, BottomSheet Behavior, or something else altogether that can help propagate the vertical scroll events on to the BottomSheet Behavior?
There's an example of the problem here:
https://github.com/timusus/bottomsheet-test
(Problem can be reproduced with commit #f59a7031)
Just expand the first bottom sheet.
Where does the problem lies? In FrameLayout. BottomSheet works perfectly when put inside CoordinatorLayout. Then BottomSheet can pass it's scrolling state through CoordinatorLayout to other views put as direct children of CoordinatorLayout.
Why RecyclerView was not able to pass scroll state to BottomSheet? It is not a direct child of CoordinatorLayout. But there exists a way to pass them: RecyclerView must be in put in view that implements NestedScrollingParent and NestedScrollingChild. The answer to that is: NestedScrollView
So your fragment_sheetX.xml layouts should look like:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:orientation="vertical"
android:fillViewport="true">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.NestedScrollView>
Notice also android:fillViewport="true" as otherwise, your RecyclerView will not take whole height.
However it still will not work. Why? RecyclerView must be told to pass vertical scrolling to parent. How? The answer is recyclerView.setNestedScrollingEnabled(false);, but that is better described here.
Btw: MultiSheetView is a great feature and a very interesting approach to mobile UX design.

Recyclerview binds all views at the same time

I have a vertical recyclerview (with a GridLayoutManager) inside another recyclerview (with LinearLayoutManager). The problem I am facing right now is that, the inner recyclerview (with GridLayoutManager) binds all of it's items at the same time, even the views that are not on the screen at the moment (onBindViewHolder() gets called for all of its items).
To give you more information, in my layout file, I put height of my recycler view as wrap_content.
I think the problem is, since there are 2 nested vertically recyclerviews, when the parent RV wants to measure its children and the children is another RV, in onMeasure() it computes the size needed for the entire RV, not just the portion that it wants to bind on the screen.
Any idea how to solve this?
Here is the layout file for my outer recyclerview:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/component_list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
And here is the code for my inner recyclerview:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/gutter"
android:paddingBottom="#dimen/gutter">
<TextView
android:id="#+id/title_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/gutter"
android:textSize="30sp"
android:textColor="#android:color/white"
android:fontFamily="sans-serif-thin"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/my_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
P.S.: I'm using this adapter delegate for my outer recyclerview:
https://github.com/sockeqwe/AdapterDelegates
I think nested recyclerviews are a very bad idea. When i try to scroll, which recyclerview has to respond the the scolling, the parrent or child.
That is why I think you are looking for the ExpandableListView? That's limited to only two levels of listings, but that sounds like it would work for your needs). It also solves the soling issue.
It would look something like this:
EDIT: even nested ExpandableListViews are possible:
EDIT: check this lib for horizontal scroling
This is a known bug.
You should not put a RecyclerView inside another RecyclerView because RecyclerView gives its children infinite space. Hence the inner RecyclerView keeps measuring till the dataset is exhausted. Try setting setAutoMeasureEnabled(false) to false on layout manager or you can solve this problem by using a wrapper adapter instead of inner recycler view.
The first thing you need to know is that, when you nest scrolling layouts, the inner ones will get infinity allowed height, effectively making them wrap_content. There is in fact a relatively easy way to fix this problem.
Say I had two nested RecyclerViews such as these, in this case vertically oriented.
<RecyclerView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical>
<View .../>
<!-- other stuff -->
<RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"/>
</RecyclerView>
The inner recyclerView here will bind all of it's children immediately every time because, from it's position, your screen will have infinite height.
The solution is to set the height of your inner recyclerview to some static value, not wrap_content or match parent, as either of those will simply fill up the outer recyclerview with one view that will all be bound at once due to it's large height. If you make the height of the inner recyclerview the same as the display's height, you should see your problem go away.
Here is an implementation that will not bind all children at once:
<RecyclerView
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="vertical>
<View .../>
<!-- other stuff -->
<RecyclerView
android:layout_width="match_parent"
android:layout_height="#dimen/screen_height"
android:orientation="vertical"/>
</RecyclerView>
Note the layout_height of the inner RecyclerView is now a fixed value pulled from the dimensions file. You yourself will have to come up with a reasonable value to put there.
Side Note: In order to make all of this work and for scrolling to work properly, you may have to play around with the parameter: NestedScrollingEnabled in your RecyclerViews - there are several known bugs relating to this that you may need to work around.
i.e.: innerRecyclerView.setHasFixedSize(true); and innerRecyclerView.setNestedScrollingEnabled(false).
so what happens here when you place a scrollview(no fixed size because of wrap content) inside another scrollview(again no fixed size because of wrap content),both nested scroll view fails to render.
So there is two solutions--
1- Either you will have to think of alternative solution for nested scrollviews
2- You can give outside recyclerview cell fixed height so that inside recycler view can get some fixed layout to render itself.
I could solve my issue by using only one Recyclerview, where it has a grid layout, and based on the component items i'm adding into it, i change the spancount for that. Basically instead of adding the inner recyclerview, i add the items that were supposed to go to the inner recyclerview, to the outer recyclerview.

How to use Recyclerview inside Scrollview [duplicate]

This question already has answers here:
RecyclerView inside ScrollView is not working
(26 answers)
Closed 7 years ago.
I'm trying to show horizontal recyclerview items and vertical recyclerview items inside an ScrollView
Scrollview didn't work even If i use android:fillViewport="true"
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
//Horizontal Recyclerview items
<RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content">
</RecyclerView>
//vertical Recyclerview items
<RecyclerView
android:layout_width="match_parent"
android:layout_height="match_parent"></RecyclerView>
</LinearLayout>
</ScrollView>
You should use NestedScrollView instead. However you may need to write your own LayoutManager. Check out this SO Answer for more details
You need to use a custom layout manager to use recyclerview inside a scrollview.
You can remove the scrollview and make a header item in the vertical recyclerview which contain the horizontal recyclerview.
Also you should not use a recyclerview inside a scrollview. So think the second approach will be better.
Also you can can use Snap-RecyclerView-Utils.
It has a linear layout manager for recyclerview inside a scroll view and an adapter which can help you make a header containing you horizontal recyclerview.
ScrollView can only have one child.
Remove your RelativeLayout and try again.
Apart from that android:layout_height in ScrollView should be set to wrap_content
Additionally I'm not quite sure, if it works, since in the Docs it is stated that
You should never use a ScrollView with a ListView, because ListView takes care of its own vertical scrolling. Most importantly, doing this defeats all of the important optimizations in ListView for dealing with large lists, since it effectively forces the ListView to display its entire list of items to fill up the infinite container supplied by ScrollView.
Maybe a NestedScrollView works since it is for
NestedScrollView is just like ScrollView, but it supports acting as both a nested scrolling parent and child on both new and old versions of Android. Nested scrolling is enabled by default.

Categories

Resources