0

I'm trying to programmatically scroll to a particular item within my RecyclerView which is nested within a NestedScrollView.

The Problem

The NestedScrollView scrolls to the complete bottom rather than the desired item.
Note: It works correctly when desired item is the 2nd item, probably since that item is visible in the screen.

What I've tried

I've searched through a dozen solutions from StackOverFlow and came up with the function below.
I've tried:

  • binding.variantsRecyclerView.getChildAt()
  • binding.variantsRecyclerView.findViewWithTag()
  • binding.variantsRecyclerView.findViewHolderForAdapterPosition()

All these do return the correct item, (I know since the edit text within that item is focused as coded) however, the NestedScrollView does not scroll correctly to that item. It is almost always scrolling to the bottom. Sometimes however it scrolls to somewhere in between the required item instead of it's start. The only time this works is when the item is either the 1st or 2nd item. (As stated before)

private fun scrollToPosition(position: Int) { if (position in 0 until variantsAdapter.itemCount) { val view = binding.variantsRecyclerView.findViewWithTag<ConstraintLayout>("pos_$position") if (view != null) { val height = binding.nestedScrollView.height val target = view.y.toInt() binding.nestedScrollView.postDelayed({ binding.nestedScrollView.smoothScrollTo(0, target) view.requestFocus() }, 200) } } } 

My XML

<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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:background="#eff1f4"> <LinearLayout>...</LinearLayout> <androidx.core.widget.NestedScrollView android:id="@+id/nestedScrollView" android:layout_width="match_parent" android:layout_height="0dp" android:fillViewport="true" app:layout_constrainedHeight="true" app:layout_constraintVertical_bias="0" app:layout_constraintBottom_toTopOf="@+id/btnNextLayout" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/toolbarLayout"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="@dimen/ui_10_dp" android:layout_marginEnd="@dimen/ui_10_dp" android:orientation="vertical"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/variantsRecyclerView" android:layout_width="match_parent" android:layout_height="wrap_content" android:clipToPadding="false" android:nestedScrollingEnabled="false" android:paddingTop="12dp" android:paddingBottom="12dp" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" tools:itemCount="2" tools:listitem="@layout/sell_variant_row_item" /> <androidx.constraintlayout.widget.ConstraintLayout> ... </androidx.constraintlayout.widget.ConstraintLayout> </LinearLayout> </androidx.core.widget.NestedScrollView> <LinearLayout>...</LinearLayout> </androidx.constraintlayout.widget.ConstraintLayout> 

My Understanding

After debugging, I found out that the NestedScrollView height is lesser than the y co-ordinate of the desired item. Hence it scrolls to the bottom of the view instead of the desired item. My understanding could be completely wrong and if so, please correct me.

1 Answer 1

2

I resolved this with a really simple fix.

private fun scrollToPosition(position: Int) { if (position in 0 until variantsAdapter.itemCount) { val view = binding.variantsRecyclerView.getChildAt(position) if (view != null) { val target = binding.variantsRecyclerView.top + view.top binding.nestedScrollView.scrollY = target } } } 

All I wanted was to get the desired item within the RecyclerView to the top of the screen.

Sign up to request clarification or add additional context in comments.

1 Comment

Seems like a good solution, but what if you want to position nested scroll view on y = 0 and recycler view item to certain position. Still finding solution to this case.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.