Reputation:
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
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 ViewHolder
s 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.
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