findLastVisibleItemPosition is returning wrong value if RecyclerView inside NestedScrollView
findLastVisibleItemPosition is returning wrong value if RecyclerView inside NestedScrollView
I have RecyclerView inside NestedScrollView
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.NestedScrollView>
I have this problem in big project and in order to find solution for this problem I have created new project without other views.
This is full code of MainActivity
class MainActivity : AppCompatActivity()
var mItems = mutableListOf<String>()
var mAdapter = MyAdapter(mItems)
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
recycler.layoutManager = LinearLayoutManager(this)
recycler.adapter = mAdapter
delayedLoadDataIfPossible(100)
recycler.viewTreeObserver.addOnScrollChangedListener
delayedLoadDataIfPossible(100)
private fun delayedLoadDataIfPossible(delay: Long)
Observable.timer(delay, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe
var scrollingReachedEnd = isScrollingReachedEnd()
if (scrollingReachedEnd)
loadData()
private fun isScrollingReachedEnd(): Boolean
val layoutManager = LinearLayoutManager::class.java.cast(recycler.layoutManager)
val totalItemCount = layoutManager.itemCount
val lastVisible = layoutManager.findLastVisibleItemPosition()
return lastVisible + 5 >= totalItemCount
private fun loadData()
Observable.timer(5, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe progress.visibility = View.VISIBLE
.doFinally progress.visibility = View.GONE
.subscribe
for (i in 1..10)
mItems.add(i.toString())
mAdapter.notifyDataSetChanged()
delayedLoadDataIfPossible(100)
I am using isScrollingReachedEnd method to identify is scrolling reaching end of list. If there are less than 5 visible items in the end, I am trying to load new data.
loadData simulates loading data. It adds 10 items to list and notifies adapter about change.
delayedLoadDataIfPossible method should work after some delay because findLastVisibleItemPosition is returning value before items are added to list. In result it is returning wrong value. For example -1 after adding first 10 items.
My problem: when RecyclerView inside NestedScrollView findLastVisibleItemPosition returning wrong value and data loading can not be stopped even there are enough items. There is no such problem when RecyclerView not inside NestedScrollView.
My question: how to get last visible item position from RecyclerView when it is inside NestedScrollView?
recyclerView.setNestedScrollingEnabled(false);
have u used findOneVisibleChild(layoutManager.getChildCount() - 1, -1, false, true)
– Ashvin solanki
Sep 7 '18 at 8:14
@NileshRathod I have tried to set nestedScrollingEnabled false but it did not help
– Joe Rakhimov
Sep 7 '18 at 9:30
Is this the issue?
– Cheticamp
Sep 11 '18 at 19:12
I would actually put those "above" views right into the
RecyclerView
itself. It means that the adapter has to manage that data, which can interfere with separation of concerns; however it gets the job done. Now you didn't post your entire activity layout with all the included layouts so I don't know if the approach is appropriate. Post more layouts and code, then I might be able to answer this for you. List models do not have to be homogeneous. Consider that the RecyclerView.Adapter
has the getItemViewType()
method so you can inflate different views based on the item position.– kris larson
Sep 13 '18 at 13:11
RecyclerView
RecyclerView.Adapter
getItemViewType()
2 Answers
2
You could try this approach:
This is my code for a ScrollingListener for a NestedScrollingView:
@Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)
int lastVisibleItemPosition = 0;
int totalItemCount = layoutManager.getItemCount();
if(v.getChildAt(v.getChildCount() - 1) != null)
if (scrollY >= (v.getChildAt(v.getChildCount()-1).getMeasuredHeight() - v.getMeasuredHeight())
&& scrollY > oldScrollY)
if (layoutManager instanceof LinearLayoutManager)
lastVisibleItemPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
if (totalItemCount < previousTotalItemCount)
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0)
this.loading = true;
if (loading && (totalItemCount > previousTotalItemCount))
loading = false;
previousTotalItemCount = totalItemCount;
if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount)
currentPage++;
onLoadMore();
loading = true;
Good luck!
If your RecyclerView
is inside a NestedScrollView
, you need to add recyclerView.setNestedScrollingEnabled(false)
to it.
RecyclerView
NestedScrollView
recyclerView.setNestedScrollingEnabled(false)
Also another note (which is unrelated to your question is that you should definitely keep a reference to those RxJava subscriptions and dispose them on Fragment/Adtivity's onStop, since they can cause memory leak issues.
Thanks for contributing an answer to Stack Overflow!
But avoid …
To learn more, see our tips on writing great answers.
Required, but never shown
Required, but never shown
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
have u set
recyclerView.setNestedScrollingEnabled(false);
– Nilesh Rathod
Sep 7 '18 at 8:11