3

I have a recyclerView inside nestedScrollView. I know it's a bad practice, but there are some cases, that I can handle only in this way.

<androidx.core.widget.NestedScrollView
    android:id="@+id/nestedScroll"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_data"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipToPadding="false"
            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
            tools:itemCount="1"
            tools:listitem="@layout/item_favorite_tournament"
            tools:visibility="visible" />

</androidx.core.widget.NestedScrollView>

And here's my code. I'll show you the scroll part, where I need to get the firstVisibleItemPosition. But it returns 0.

private void initList(RecyclerView recycler, View labelNoResults) {
    recycler.setAdapter(mAdapter);
    recycler.setHasFixedSize(true);
    mListLayoutManager = Objects.requireNonNull((LinearLayoutManager) recycler.getLayoutManager());


    recycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            final int p = mListLayoutManager.findFirstVisibleItemPosition();
            Log.d("Tag_1", "Position: " + p);
        }
    });
}

I think the problem is because of nestedScrollView. So how can I get the visibleItemPosition form recyclerView? Thank you.

Hayk Mkrtchyan
  • 2,835
  • 3
  • 19
  • 61
  • It returns `0` because the first item is effectively the "first visible item". The "first visible item" in this case is just the position of the first bound view holder. When you put a RecyclerView in a NestedScrollView, no recycling happens, all items are bound at all times, so the first bound view holder is always the first one. This is because the RecyclerView has unbound height, so it takes all the space it can. – Nicolas May 01 '20 at 16:21
  • Thanks . And is there a way to solve this? – Hayk Mkrtchyan May 01 '20 at 16:22
  • I think it's possible to make a custom layout manager, but that seems complex and I have no idea how to do it. Why do you need a NestedScrollView to start with? I'm guessing you have other views shown above or under the RecyclerView? In this case, you need to ditch the NestedScrollView and show those views by using multiple view types. – Nicolas May 01 '20 at 16:24
  • Yeah. I have also one recyclerView under this. That will be long to explain, so why am I using this instead of multiple view types? I have 2 recyclerviews and I'm getting data for them from different sources. Also the second recyclerview has pagination, but the first hasn't and I need to update only the second recycler time by time. – Hayk Mkrtchyan May 01 '20 at 16:27
  • But anyway thank you, I'll try my best to implement it with multiple view types – Hayk Mkrtchyan May 01 '20 at 16:39
  • I know it can get complex sometimes. I don't use them personally but if you want, there are some libraries that might simplify this, like Groupie. – Nicolas May 01 '20 at 16:44
  • Yeah, also I've noticed that they made a new update of recyclerView, where they've added MergeAdapter, that allows us to use multiple adapters for one recyclerview. Also it can fix my problem, but it's in alpha version yet))) – Hayk Mkrtchyan May 01 '20 at 16:47
  • Have you found a solution for this problem, I ran into the same issue – Regex Jan 10 '21 at 04:11

1 Answers1

7

The easiest way to fix this would be to replace NestedScrollView by simply ScrollView. This of course will change the behavior of your layout, but it will show you the right position.

In case of NestedScrollView, findFirstVisibleItemPosition() always returns 0 and findLastVisibleItemPosition() always returns the last item in the RecyclerView despite whether they are visible to the user or not. This happens because RecyclerView placed inside NestedScrollView behaves like a ListView without doing any recycling. Meaning all items are visible at the same time because all of them are bind at the same time.

Javad Dehban
  • 1,282
  • 3
  • 11
  • 24
Sam
  • 112
  • 1
  • 8