9

I have implemented a recycleview inside a nested scroll view. But recycle view scroll to position methods are not working.

Below is my sample code

  <?xml version="1.0" encoding="utf-8"?>
  <android.support.v4.widget.NestedScrollView 
    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"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

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


  <android.support.v7.widget.RecyclerView
      android:id="@+id/list_view"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

 </LinearLayout>

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

below is the method for scrolling

RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(this) {
                @Override
                protected int getVerticalSnapPreference() {
                    return LinearSmoothScroller.SNAP_TO_START;
                }
            };
            smoothScroller.setTargetPosition(pos);
            recyclerView.getLayoutManager().startSmoothScroll(smoothScroller);
Darshana
  • 406
  • 5
  • 18

7 Answers7

16

This is how I resolve this issue

first get recycle view position that need to scroll using below method

final float y = recyclerView.getChildAt(selectedItem.getPos()).getY();

Then scroll nested scroll view to that position

nestedScrollingView.post(new Runnable() {
                    @Override
                    public void run() {
                        nestedScrollingView.fling(0);
                        nestedScrollingView.smoothScrollTo(0, (int) y);
                    }
                });

Don't forget to add android:fillViewport="true" on nestedscrollview

ganjaam
  • 1,030
  • 3
  • 17
  • 29
Darshana
  • 406
  • 5
  • 18
  • 2
    thanks for this, it works for me with an additional step: `final float y = recyclerView.getY() + recyclerView.getChildAt(adapterPosition).getY(); scrollView.post(() -> { scrollView.fling(0); scrollView.smoothScrollTo(0, (int) y); });` – Noam a Aug 02 '18 at 13:58
8

The thing is that you need to scroll the NestedScrollView, not the RecyclerView. E.g:

final float y = recyclerView.getChildAt(selectedItem.getPos()).getY(); 

scrollView.smoothScrollTo(0, y)
Chintan Rathod
  • 25,864
  • 13
  • 83
  • 93
Gabor
  • 136
  • 1
  • 4
  • I've tried everything on this site and this is the one solution that finally worked for me. It's very easy to forget that NestedScrollView controls the scrolling and get confused. Small edit: y now needs to be an "int" instead of float. – curious_george Aug 25 '20 at 03:02
1
<android.support.design.widget.CoordinatorLayout
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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">

<android.support.design.widget.AppBarLayout
    android:id="@+id/appBar"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
    android:fitsSystemWindows="true">

    <android.support.design.widget.CollapsingToolbarLayout
        android:id="@+id/collapsingToolbar"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_scrollFlags="scroll|exitUntilCollapsed"
        android:fitsSystemWindows="true"
        app:contentScrim="?attr/colorPrimary"
        app:expandedTitleMarginStart="48dp"
        app:expandedTitleMarginEnd="64dp"
        app:title="Scroll">

        <ImageView
            android:id="@+id/toolbarImage"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scaleType="centerCrop"
            android:fitsSystemWindows="true"
            android:src="@mipmap/ic_launcher"
            app:layout_collapseMode="parallax" />

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_collapseMode="pin" />
    </android.support.design.widget.CollapsingToolbarLayout>

</android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:id="@+id/recycler_view"
        android:scrollbars="vertical"
        android:nestedScrollingEnabled="false"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

Remove the NestedScrollView and add

app:layout_behavior="@string/appbar_scrolling_view_behavior"

to your Recyclerview.Then ScrollToPosition works fine.

Dino Sunny
  • 921
  • 1
  • 10
  • 18
0

Try this,

new Handler().postDelayed(new Runnable() {
@Override
public void run() {
    recyclerview.scrollToPosition(position);
}
}, 200);
hasan_shaikh
  • 1,434
  • 1
  • 15
  • 38
0

Use this:

yourRecyclerView.setNestedScrollingEnabled(false);

It may solve your problem.

Anton Prokopov
  • 639
  • 6
  • 27
0

You can use this extenstion function.

fun RecyclerView.nestedScrollTo(position:Int,nestedScrollView: NestedScrollView) {
    val y = getChildAt(position).y

    nestedScrollView.fling(0)
    nestedScrollView.smoothScrollTo(0,y.toInt())
}
xaldarof
  • 75
  • 1
  • 7
0

In my case, it worked 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)