RecyclerView inside ScrollView is not working

243,996

Solution 1

use NestedScrollView instead of ScrollView

Please go through NestedScrollView reference document for more information.

and add recyclerView.setNestedScrollingEnabled(false); to your RecyclerView

Solution 2

I know I am late it the game, but the issue still exists even after google has made fix on the android.support.v7.widget.RecyclerView

The issue I get now is RecyclerView with layout_height=wrap_content not taking height of all the items issue inside ScrollView that only happens on Marshmallow and Nougat+ (API 23, 24, 25) versions.
(UPDATE: Replacing ScrollView with android.support.v4.widget.NestedScrollView works on all versions. I somehow missed testing accepted solution. Added this in my github project as demo.)

After trying different things, I have found workaround that fixes this issue.

Here is my layout structure in a nutshell:

<ScrollView>
  <LinearLayout> (vertical - this is the only child of scrollview)
     <SomeViews>
     <RecyclerView> (layout_height=wrap_content)
     <SomeOtherViews>

The workaround is the wrap the RecyclerView with RelativeLayout. Don't ask me how I found this workaround!!! ¯\_(ツ)_/¯

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

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

</RelativeLayout>

Complete example is available on GitHub project - https://github.com/amardeshbd/android-recycler-view-wrap-content

Here is a demo screencast showing the fix in action:

Screencast

Solution 3

Although the recommendation that

you should never put a scrollable view inside another scrollable view

Is a sound advice, however if you set a fixed height on the recycler view it should work fine.

If you know the height of the adapter item layout you could just calculate the height of the RecyclerView.

int viewHeight = adapterItemSize * adapterData.size();
recyclerView.getLayoutParams().height = viewHeight;

Solution 4

In case setting fixed height for the RecyclerView didn't work for someone (like me), here is what I've added to the fixed height solution:

mRecyclerView.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        int action = e.getAction();
        switch (action) {
            case MotionEvent.ACTION_MOVE:
                rv.getParent().requestDisallowInterceptTouchEvent(true);
                break;
        }
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {

    }

    @Override
    public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {

    }
});

Solution 5

The new Android Support Library 23.2 solves that problem, you can now set wrap_content as the height of your RecyclerView and works correctly.

Android Support Library 23.2

Share:
243,996
royB
Author by

royB

Updated on December 26, 2021

Comments

  • royB
    royB over 2 years

    I'm trying to implement a layout which contains RecyclerView and ScrollView at the same layout.

    Layout template:

    <RelativeLayout>
        <ScrollView android:id="@+id/myScrollView">
           <unrelated data>...</unrealated data>
    
               <android.support.v7.widget.RecyclerView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:id="@+id/my_recycler_view"
                />
        </ScrollView>
    
    
    </RelativeLayout>
    

    Problems: i can scroll until the last element of ScrollView

    Things i tried:

    1. card view inside the ScrollView (now ScrollView contains RecyclerView) - can see the card up until the RecyclerView
    2. initial thought was to implement this viewGroup using RecyclerView instead of ScrollView where one of it's views type is the CardView but i got the exact same results as with the ScrollView
  • Krutik
    Krutik almost 9 years
    How to get adapterItemSize in recyclerview any idea?
  • PGMacDesign
    PGMacDesign almost 9 years
    Indeed, this worked well for me. With this in place, I was able to move the scroll view up and down, and when I select the recyclerview for scrolling, it takes priority over the scroll view. Thanks for the tip
  • Ersen Osman
    Ersen Osman almost 9 years
    I set the height to be fixed but this disabled scrolling for me. How would i re-enable it. I simply did the above code amount of dp to px times size of items.
  • Vaibhav Jani
    Vaibhav Jani almost 9 years
    It works like a charm! Little correction it should be : int viewHeight = adapterItemSize * adapterData.size(); recyclerView.getLayoutParams().height = viewHeight;
  • BigBen3216
    BigBen3216 almost 9 years
    it worked for me too, just be sure to use getParent on a direct child of the scrollview
  • droidster.me
    droidster.me over 8 years
    How to find out adapterItemSize?
  • Ashkan
    Ashkan over 8 years
    i have a page with more than one Recycler, is there any other way to persuade this? some thing like instagram or google play part comment that load more record when you click on more comment
  • EC84B4
    EC84B4 over 8 years
    make it a single recyclerView and put your views as items for that recycler
  • Simon
    Simon over 8 years
    This would work only provided that your children can be garbaged collected as soon as you scroll them out of view. If you have children that are mapFragments or streetviews, it doesn't make sense as they are forced to reload each time they scroll off the recyclerview. Embedded them into a scrollview and then generating a recyclerview at the bottom makes more sense then.
  • IgorGanapolsky
    IgorGanapolsky over 8 years
    @JoakimEngstrom What is the adapterItemSize variable?
  • IgorGanapolsky
    IgorGanapolsky over 8 years
    That is nonsense. You can have nested RecyclerViews just fine.
  • Asthme
    Asthme over 8 years
    it will work.but it still consumes some event .not good for performance
  • ernazm
    ernazm over 8 years
    @Simon there's handy setIsRecyclable() in ViewHolder
  • H Raval
    H Raval over 8 years
    when i put recyclerview inside scroll view, my adapter is never call....any suggestion?
  • HappyKatz
    HappyKatz over 8 years
    This method works on cyanogenmod distributions as well. The fixed height solution on cyanogenmod works, but only if the fixed height is the absolute height of all of the items in the list, which defies the point of using the recyclerview in the first place. Upvoted.
  • Joakim Engstrom
    Joakim Engstrom over 8 years
    For those having problems with touch events, either see if you override onInterceptTouch anywhere, and see what is done there. If you don't maybe it's a good idea too look at that api. Touch events are a tricky thing in android.
  • Eshaan
    Eshaan over 8 years
    Couldn't you call setNestedScrollingEnabled(false) on the recyclerview?
  • winsontan520
    winsontan520 about 8 years
    Tested working fine using v23.2.1 . Was using it for adding layout above recyclerview.
  • Milan Gajera
    Milan Gajera about 8 years
    How can i call this class when we set the data to adapter?
  • abhishesh
    abhishesh almost 8 years
    Avoid recycler view inside Scroll view, because scroll view give its child infinite space. This causes recycler view having wrap_content as height to measure infinitely in vertical direction(till the last item of recycler view). Instead of using recycler view inside scroll view, use only recycler view with different item types. With this implementation, children of scroll view would behave as as view type. Handle those viewtypes inside recycler view.
  • behelit
    behelit almost 8 years
    doesn't fling properly too (23.4.0)
  • cyroxis
    cyroxis almost 8 years
    RecyclerView replaces ListView it is not meant to replace ScrollView.
  • Samad
    Samad almost 8 years
    just the RecyclerView scrolling and the ScrollView not scrolling
  • Samad
    Samad almost 8 years
    @behelit 23.4.0 have some issues code.google.com/p/android/issues/detail?id=210085#makechange‌​s , use 23.2.1 instead
  • Masoud Dadashi
    Masoud Dadashi almost 8 years
    nested scroll view is made for such a purpose already. this recommendations is not recommended?
  • MohanRaj S
    MohanRaj S almost 8 years
    Bro, Still have the Same Problem After changed into NestedScrollview from the Scrollview.
  • royB
    royB almost 8 years
    mmm...can you share some code...I'm having zero issues but u can never know with this kind of issues
  • Joakim Engstrom
    Joakim Engstrom over 7 years
    @MasoudDadashi Yes, you are right, this answer is not the best answer anymore.
  • Cocorico
    Cocorico over 7 years
    Works with : android.support.v4.widget.NestedScrollView
  • Analizer
    Analizer over 7 years
    I also needed recyclerView.setNestedScrollingEnabled(false);
  • rahulrvp
    rahulrvp over 7 years
    using simple wrap_content as layout_height worked for me. No need of calculating the height.
  • Tapa Save
    Tapa Save over 7 years
    What about layouts below RecyclerView?
  • Zeeshan Shabbir
    Zeeshan Shabbir over 7 years
    that works as well. You just need to use. NestedScrollView instead of scroll view
  • Tapa Save
    Tapa Save over 7 years
    Yes, only NestedScrollView. But solution with NestedScrollView+RecycleView call very slow populations of RecyclerView (I think for calcutaion of Y-position of first view after RecyclerView)
  • Corey Horn
    Corey Horn about 7 years
    This answer is now outdated. We have things like NestedScrollView that allow for nested scrollable views. Nested RecyclerViews also now work.
  • Sagar Chavada
    Sagar Chavada about 7 years
    Thanks man.. its help a lot.. but scrolling become hard after your solution so i set recyclerview.setNestedScrollingEnabled(false); and now its work like a charm.
  • Sarath Babu
    Sarath Babu about 7 years
    keep android:layout_height="wrap_content" for the layout inflated for ViewHolder
  • Kai Wang
    Kai Wang almost 7 years
    This comment deserves better. It is a solution, and even better than the accepted one.
  • androidXP
    androidXP almost 7 years
    Is this method recycle views? if we have around hundreds of object to be recycle. This is hack not solution.
  • maruti060385
    maruti060385 almost 7 years
    doesnt even fling properly on 25.0.1
  • Roman Samoilenko
    Roman Samoilenko almost 7 years
    In a complex layout NestedScrollView lags for me, unlike the ScrollView. Searching for a solution without using NestedScrollView
  • Hossain Khan
    Hossain Khan over 6 years
    Yes, @androidXP is right, this hack is not a solution for a long list. My use case was fixed item in a list view which was less than 10. And as for how I found the other workaround, I was trying random things, this was one of them :-)
  • Amir Ziarati
    Amir Ziarati over 6 years
    perfect.solved my problem in adnroid marshmallow and upper. ;)
  • jk7
    jk7 over 6 years
    Some comments on a similar answer say disabling nested scrolling defeats the purpose of using a RecyclerView, i.e. that it won't recycle views. Not sure how to confirm that.
  • jk7
    jk7 over 6 years
    Setting nestedScrollingEnabled="false" causes RecyclerView to NOT recycle its views, at least in my setup (a RecyclerView inside a NestedScrollView). Confirmed by adding a RecyclerListener to the RecyclerView and setting a breakpoint inside its onViewRecycled() method.
  • chetan
    chetan over 6 years
    It's working but my requirement is different, I have RecyclerView inside NestedScrollView and implementing paging for recyclerview and listening for the last position to fetch next data but it's not wokring, if I remove ScrollView or NestedScrollview then it's working fine. Is there any solution for this?
  • Hemant Kaushik
    Hemant Kaushik over 6 years
    For below Lollipop versions: stackoverflow.com/a/43450158/7784230
  • mehmet
    mehmet over 6 years
    I think your solution is better but when I removed "setHasFixedSize(true);" it works more better
  • Umar Ata
    Umar Ata about 6 years
    Very bad solution, I mean we use recyclerview just to reuse the old views and if we assign the fixed height to recyclerview by your formula then recyclerview will not reuse that
  • thedarkpassenger
    thedarkpassenger almost 6 years
    using RecyclerView inside NestedScrollView is calling onBindView for every item in the list even if the item is not visible. Any solution for that problem?
  • thedarkpassenger
    thedarkpassenger almost 6 years
    if I use this solution, then onBindView is getting called for all the items in the list, which is not the usecase of recyclerview.
  • thedarkpassenger
    thedarkpassenger almost 6 years
    using this code calls onBindView for all the items in the list even if those items are not visible in the list. This defeats the purpose of recyclerview.
  • Abror Esonaliev
    Abror Esonaliev over 5 years
    android:descendantFocusability="blocksDescendants" helped me
  • Liar
    Liar over 5 years
    Show how can I make RecyclerView recycle even inside ScollView? Thanks!
  • Linh
    Linh over 5 years
    @Liar, currently there is no way to make RecyclerView recycle after put it to ScrollView. If you want recycle, thinking about another approach (like using RecyclerView with multiple type)
  • Taufik Nur Rahmanda
    Taufik Nur Rahmanda over 5 years
    Please don't ... check your memory usage. This hack is killing what "recycler" means.
  • Hossain Khan
    Hossain Khan over 5 years
    As I mentioned earlier, this is intended for a small list. I've also used it for long list with images without issue except memory consumption. So, yes, anybody planning to use this for long list is not a good idea.
  • Prince Dholakiya
    Prince Dholakiya over 5 years
    In my case, I did took Horizontal RecyclerView within HorizontalScrollView and I also write this statement but It can't show me all the data which I stored in horizontal recyclerview
  • kostyabakay
    kostyabakay about 5 years
    Also you can add android:nestedScrollingEnabled="false" to XML instead of recyclerView.setNestedScrollingEnabled(false);
  • Nanda Z
    Nanda Z about 5 years
    This is not working if your data recyclerview source coming from api and you add "load more" feature. it will be load all data and would cause OutOfMemoryError
  • akshay bhange
    akshay bhange about 5 years
    this worked for me but I have expandable items in recyclerview & the last item expands below visible screen . this wasn't the case with scrollView
  • Mostafa Arian Nejad
    Mostafa Arian Nejad about 5 years
    It worked for me but keep in mind that the items inside recyclerView are not getting recycled.
  • Hossain Khan
    Hossain Khan about 5 years
    The use case I had was for limited fixed size items that look similar. As I mentioned earlier, don't use if the list size is dynamic and you expect to add more items dynamically.
  • Nanda Z
    Nanda Z almost 5 years
    it only for api level 21, how about level 19?
  • Thijs
    Thijs over 4 years
    For those who stumble onto this answer and did everything right. hasFixedSize must be set to false on recyclerview for this to work.
  • CoolMind
    CoolMind over 4 years
    @NandaZ, ViewCompat.setNestedScrollingEnabled(recyclerView, false).
  • CoolMind
    CoolMind over 4 years
    @Thijs, setHasFixedSize(true) works right in my case.
  • Gary Chen
    Gary Chen over 3 years
    You're genius! Awesome.
  • martinseal1987
    martinseal1987 over 3 years
    you can give the recycler view a set height
  • oalpayli
    oalpayli over 3 years
    You just need to give PaddingBottom into LinearLayout that is inside nestedScrollView - @thedarkpassenger
  • Selva
    Selva almost 3 years
    I used stickyScrollview, and recyclerview was going above the StickyHeader, actually it should go below, after applying your solution, it worked like charm :) great man and thanks a ton.
  • cascal
    cascal almost 3 years
    The correct package to use is now androidx.core.widget.NestedScrollView
  • Tamoxin
    Tamoxin about 2 years
    This really worked! It never occurred to me to set a touch listener at the item level. I tried (with no luck) to set a touch listener at the recyclerView level. Great solution. Cheers!
  • Raykud
    Raykud almost 2 years
    @HossainKhan thank you. The fix without the nestedscroll worked for me, however its worth pointing out that ONLY RelativeLayout works, I tested Linear and Constraint and it wont work for some reason.