6

I have a recyclerView and each of it's item is a recyclerView. I want scroll to custom position of inner recyclerView at specific condition. I used this code at innerRecyclerView but it didn't work:

innerRecyclerView.smoothScrollToPosition(position); 

and this:

innerRecyclerView.scrollToPosition(position); 

and this one:

layoutManager.scrollToPositionWithOffset(position, offset);

Now I have two question:

1) Is it possible scroll to custom position of inner recyclerView?

2) If that is possible, how?

Here is initialize main recyclerView:

LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), RecyclerView.VERTICAL, false);
        adapter = new FreightsListRVAdapter(new FreightListCallBack(), new FreightListVHFactory());
        rvFreightsList.setLayoutManager(layoutManager);
        rvFreightsList.setItemViewCacheSize(30);
        rvFreightsList.setNestedScrollingEnabled(true);
        rvFreightsList.setAdapter(adapter);

Here is initialize innerRecyclerview:

LinearLayoutManager layoutManager = new LinearLayoutManager(itemView.getContext(), RecyclerView.VERTICAL, false);
        layoutManager.setItemPrefetchEnabled(true);
        layoutManager.setInitialPrefetchItemCount(7);
        rvFreights.setNestedScrollingEnabled(false);
        rvFreights.setLayoutManager(layoutManager);
        rvFreights.setItemViewCacheSize(20);

        adapter = new FreightsRVAdapter(new FreightCallBack(), new FreightSingleVHFactory());
        rvFreights.setAdapter(adapter);

Here is my main recyclerView adapter:

public class FreightsListRVAdapter extends ListAdapter<FreightListModel, FreightListVH> {

    private final FreightListVHFactory mFactory;
    private final PublishSubject<FreightListVHAction> mClickUserPS = PublishSubject.create();

    @Inject
    public FreightsListRVAdapter(@NonNull FreightListCallBack diffCallback, FreightListVHFactory factory) {
        super(diffCallback);
        mFactory = factory;
    }

    @NonNull
    @Override
    public FreightListVH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return mFactory.create(parent);
    }

    @Override
    public void onBindViewHolder(@NonNull FreightListVH holder, int position) {
        holder.getVM().setObject(getItem(position));
        holder.bind();
        holder.itemOnClick(mClickUserPS);

    }

    public PublishSubject<FreightListVHAction> getmClickUserPS() {
        return mClickUserPS;
    }
}

Here is layout of each row of mainRecyclerView:

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat 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:descendantFocusability="blocksDescendants"
    android:orientation="vertical">

    <androidx.appcompat.widget.AppCompatTextView 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:id="@+id/txtDescription"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingLeft="10dp"
        android:paddingTop="5dp"
        android:paddingRight="10dp"
        android:textColor="#992C2C2C"
        android:textSize="11sp"
        app:fontFamily="@font/iransans"
        tools:ignore="HardcodedText,SmallSp" />

    <androidx.appcompat.widget.AppCompatTextView
        android:id="@+id/txtDate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:layout_marginBottom="15dp"
        android:gravity="right"
        android:textColor="#2C2C2C"
        android:textSize="20sp"
        app:fontFamily="@font/iransans_medium"
        tools:ignore="RtlHardcoded"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvFreights"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:overScrollMode="never"
        android:scrollbars="none" />
</androidx.appcompat.widget.LinearLayoutCompat>
Shrey Garg
  • 1,317
  • 1
  • 7
  • 17
Masoud Mokhtari
  • 2,390
  • 1
  • 17
  • 45
  • Thank you for that. @Zoe – Masoud Mokhtari Feb 25 '19 at 13:59
  • Try using innerRecyclerView.scrollToPosition(position); – Shivam Yadav Feb 25 '19 at 14:01
  • You need to store a reference of inner RecylerView in some Arraylist (as outer one is dynamic) and later on you can scroll using that reference. Don't forget to push reference in `onBindMethod` of outer RecylerView – Firdous nath Feb 25 '19 at 14:04
  • @ShivamYadav not worked. – Masoud Mokhtari Feb 25 '19 at 15:15
  • @Firu I try that but not worked. – Masoud Mokhtari Feb 25 '19 at 15:16
  • not sure if this will work in your case: https://stackoverflow.com/questions/52083678/nestedscrollviews-smoothscrollto-behaves-weird – user1506104 Mar 13 '19 at 18:16
  • @user1506104 didn't worked. – Masoud Mokhtari Mar 14 '19 at 05:21
  • Have you tried this [solution](https://stackoverflow.com/questions/11431832/android-smoothscrolltoposition-not-working-correctly) – Abid Khan Mar 18 '19 at 12:38
  • @AbidKhan I tried but not worked. – Masoud Mokhtari Mar 18 '19 at 12:47
  • And have you tried setSelection() method? – Abid Khan Mar 18 '19 at 12:54
  • And you should also try `layoutManager.smoothScrollToPosition(recyclerView, new RecyclerView.State(), position);` if the setSelectionMethod doesn't works for you. – Abid Khan Mar 18 '19 at 12:59
  • It is possible to scroll an inner `RecyclerView` and it is quite straight forward, you just get the inner recycler view instance and call the scrollToPosition method on it. However as you've said you haven't found any luck doing so. Can you instead show how you are getting the inner `RecyclerView`? I recommend `mainRecyclerView.findViewHolderForPosition()` This will return `LinearLayoutCompat`, however you can then use `findByViewId(R.id.rvFreights)` on it to get the `RecyclerView`. – Abbas Mar 18 '19 at 13:01
  • all recycler are vertical, this is bad for performance, the nested recycler will draw all items on initialization... layout manager will no be able to scroll to nested scroll position, the best way is to merge on 1 recycler. If it's too hard to do, you can try this. You have to use the nested scrollView and retrieve the ViewHolder using findViewHolderForAdapterPosition. with the viewholder.itemView, use layoutManager, getDecoratedBoundsWithMargins to get Y bound, after that, on main recycler layout manager call scrollToPositionWithOffset, with position in main recycler and Y as offset. – Anis BEN NSIR Mar 19 '19 at 18:00

2 Answers2

1

In Kotlin-androidX recyclerview solution

val parentViewHolder = parentRecyclerView?.findViewHolderForAdapterPosition(parentPosition) as? ParentViewHolder?

var childY = 0F
if (parentViewHolder != null)
  childY = parentViewHolder.childRecyclerView?.getChildAt(lastPosition)?.y ?: 0F
parentRecyclerView.scrollBy(0, childY.toInt())

PrentViewHolder.kt

class PrentViewHolder(
    view: InflateBinding
): RecyclerView.ViewHolder(view.root) {
    var recyclerView: RecyclerView? = null

    fun populateData(data: Data) {
        viewDataBinding.recyclerview.adapter = adapter
        recyclerView = viewDataBinding.recyclerview
    }
}
Aman Kumar
  • 244
  • 1
  • 10
0

Can you please try this:

 float y = recyclerView.getY() + recyclerView.getChildAt(selectedPosition).getY();    
 mainRecyclerview.smoothScrollTo(0, (int) y);
Jiten Basnet
  • 1,623
  • 15
  • 31