user10704360
user10704360

Reputation:

Scrolltoposition/ smoothscrolltoposition for recyclerview under a nestedscrollview layout

I have a recyclerview under a nestedsrcollview. I want to implement the scrolling to a specific position for the recyclerview but I am having difficulty with it. The xml code is:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".HomeFragment"
    android:background="#ffffff"

    android:fillViewport="true"
    android:id="@+id/nestedscrollview"
    >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dp"
        android:orientation="vertical"
        >

       <<some other layouts>>

        <android.support.v7.widget.RecyclerView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/home_blog_list"

            android:layout_marginBottom="52dp"

            />





    </LinearLayout>




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

I want to implement the scrolltoposition for the home_blog_list recyclerview to a position (say 26). How to do it? P.S.- I have set nestedscrollingenabled to false for the home_blog_list.Please note that I want to scroll the nestedscrollview to a specific row of the recyclerview. I dont want the case where the recyclerview is scrolled only. Thanks in advance!

Upvotes: 2

Views: 1672

Answers (2)

Mackovich
Mackovich

Reputation: 3573

I stumbled into the same issue and I found an easy solution that does not require to refactor by using the library suggested by asif-ali.

On my current project, I have a NestedScrollView that holds a ConstraintLayout. This ConstraintLayout contains a complex header made of multiple view, and then my RecyclerView.

Much like you, I needed the whole thing to be scrollable.

That said, when the user wishes to see an item from the particular RecyclerView, you would normally call:

RecyclerView#smoothScrollToPosition(int position)

But since the RecyclerView's height is set to wrap_content the full list is displayed, with as many ViewHolders as there are items in its adapter. Granted, we do not benefit from recycling, but then why would we need a ScrollView ? Using @asif-ali solution might surely bring recycling optimizations but that's not the point here.

So, we have a fully laid-out RecyclerView. In order to scroll to a particular item (ViewHolder#itemView) position, you can do as followed:

final void smoothScrollToPosition(final int position) {
    final ViewHolder itemViewHolder = this.recyclerView.findViewHolderForAdapterPosition(position);
    // at this point, the ViewHolder should NOT be null ! Or else, position is incorrect !

    final int scrollYTo = (int) itemViewHolder.itemView.getY();
    // FYI: in case of a horizontal scrollview, you may use getX();
    this.nestedScrollView.smoothScrollTo(
        0, // x - for horizontal
        scrollYTo
    );
}

That's it ! It might be possible child is not fully visible after doing so (in my test case) so I'd suggest to add half the height of the itemView to the scrollYTo variable to make sure the nestedScrollView will scroll enough. If you do so, you might also want to check out in which direction the nestedScrollView must scroll to (either up, then remove half height, or down, then add half height.


[EDIT 1]

After further testing and research, based on this answer: https://stackoverflow.com/a/6831790/3535408 it is actually better and simpler to target the itemView.getBottom. On my app, it works flawlessly.

So the updated code looks as followed:

final void smoothScrollToPosition(final int position) {
    final ViewHolder itemViewHolder = this.recyclerView.findViewHolderForAdapterPosition(position);
    // at this point, the ViewHolder should NOT be null ! Or else, position is incorrect !

    // FYI: in case of a horizontal scrollview, you may use getX();
    this.nestedScrollView.smoothScrollTo(
        0, // x - for horizontal
        itemViewHolder.itemView.getBottom()
    );
}

Upvotes: 3

asif ali
asif ali

Reputation: 108

I think this is what you want, have a look: link

Upvotes: 1

Related Questions