How To Tell Recyclerview To Start At Specific Item Position
Solution 1:
I found a solution myself:
I extended the LayoutManager:
classMyLayoutManagerextendsLinearLayoutManager {
privateintmPendingTargetPos= -1;
privateintmPendingPosOffset= -1;
@OverridepublicvoidonLayoutChildren(Recycler recycler, State state) {
if (mPendingTargetPos != -1 && state.getItemCount() > 0) {
/*
Data is present now, we can set the real scroll position
*/
scrollToPositionWithOffset(mPendingTargetPos, mPendingPosOffset);
mPendingTargetPos = -1;
mPendingPosOffset = -1;
}
super.onLayoutChildren(recycler, state);
}
@OverridepublicvoidonRestoreInstanceState(Parcelable state) {
/*
May be needed depending on your implementation.
Ignore target start position if InstanceState is available (page existed before already, keep position that user scrolled to)
*/
mPendingTargetPos = -1;
mPendingPosOffset = -1;
super.onRestoreInstanceState(state);
}
/**
* Sets a start position that will be used <b>as soon as data is available</b>.
* May be used if your Adapter starts with itemCount=0 (async data loading) but you need to
* set the start position already at this time. As soon as itemCount > 0,
* it will set the scrollPosition, so that given itemPosition is visible.
* @param position
* @param offset
*/publicvoidsetTargetStartPos(int position, int offset) {
mPendingTargetPos = position;
mPendingPosOffset = offset;
}
}
It stores my target position. If onLayoutChildren
is called by RecyclerView, it checks if adapters itemCount is already > 0. If true, it calls scrollToPositionWithOffset()
.
So I can tell immediately what position should be visible, but it will not be told to LayoutManager before position exists in Adapter.
Solution 2:
You can try this, it will scroll to a position you want:
rv.getLayoutManager().scrollToPosition(positionInTheAdapter).
Solution 3:
If you want to scroll to a specific position and that position is the adapter's position, then you can use StaggeredGridLayoutManager
scrollToPosition
StaggeredGridLayoutManagerstaggeredGridLayoutManager=newStaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL);
staggeredGridLayoutManager.scrollToPosition(10);
recyclerView.setLayoutManager(staggeredGridLayoutManager);
If I understand the question, you want to scroll to a specific position but that position is the adapter's position and not the RecyclerView's item position.
You can only achieve this through the LayoutManager
.
rv.getLayoutManager().scrollToPosition(youPositionInTheAdapter);
Solution 4:
None of the methods above worked for me. I did the following using ViewTreeObserver that is triggered once its children have been added/changed visibility.
recyclerView.apply {
adapter = ...
layoutManager = ...
val itemCount = adapter?.itemCount ?: 0if(itemCount > 1) {
viewTreeObserver.addOnGlobalLayoutListener(object: ViewTreeObserver.OnGlobalLayoutListener {
overridefunonGlobalLayout() {
viewTreeObserver.removeOnGlobalLayoutListener(this)
(layoutManager as? LinearLayoutManager)?.scrollToPosition(#PositionToStartAt)
}
}
}
Go ahead and set #PositionToStartAt to a specific value. You can also ensure that the RecyclerView initial position setting gets triggered once a specific number of children have been laid out to ensure it is set correctly.
if(recyclerView.childCount() > #PositionCheck) {
viewTreeObserver.removeOnGlobalLayoutListener(this)
(layoutManager as? LinearLayoutManager)?.scrollToPosition(#PositionToStartAt)
}
Solution 5:
If your only motive is to start the recyclerView from a specific position without any scroll-like animation I'll suggest using StaggeredGridLayoutManager
valstaggeredGridLayoutManager= StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.HORIZONTAL)//or VERTICAL
staggeredGridLayoutManager.scrollToPosition(specificPosition)
recyclerView.apply{
layoutManager = staggeredGridLayoutManager
}
Post a Comment for "How To Tell Recyclerview To Start At Specific Item Position"