Reputation: 2178
I am working on an Android app that runs on only one devicerunning KitKat.
The smooth scrolling feature for a RecylerView I used that was working on other physical tablets and genymotion has unfortunately stopped working on the one device it needs to work on.
Instead of scrolling to a certain position it passes over the target position and scrolls all the way to the bottom and looks really bad.
I am able to track down the error to the abstract SmoothScroller in the RecyclerView class.
if (getChildPosition(mTargetView) == mTargetPosition) {
onTargetFound(mTargetView, recyclerView.mState, mRecyclingAction);
mRecyclingAction.runIfNecessary(recyclerView);
stop();
} else {
Log.e(TAG, "Passed over target position while smooth scrolling.");
mTargetView = null;
}
I was using a SnappingLinearLayoutManager that I found online, but swapped it out with the normal LinearLayoutManager from Android, and still am having the same problem.
The list is 7 items long (user can see 4 at a time) and I scroll to the 5th item (position 4) item.
When I scroll to the 3rd I don't receive this error.
Also after I scroll the list up and down once, the error stops happening.
EDIT: I am able to use layoutManager.scrollToPositionWithOffset(); But I am trying to do this with the smooth scroll animation.
Here is some of my code and details:
private void setupMainRecyclerViewWithAdapter() {
mainLayoutManager = new SnappingLinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
mainListRecyclerView.setLayoutManager(mainLayoutManager);
settingsMainListAdapter = new SettingsListAdapter(SettingsActivity.this,
settingsPresenter.getSettingsItems(),
settingsPresenter);
mainListRecyclerView.setAdapter(settingsMainListAdapter);
mainListRecyclerView.addItemDecoration(new BottomOffsetDecoration(EXTRA_VERTICAL_SCROLLING_SPACE));
}
@Override
public void scrollMainList(boolean listAtTop) {
if(listAtTop) {
mainListRecyclerView.smoothScrollToPosition(4);
moveMainMoreButtonAboveList();
} else {
mainListRecyclerView.smoothScrollToPosition(0);
moveMainMoreButtonBelowList();
}
}
Upvotes: 2
Views: 7351
Reputation: 41
Well, I realize it's too late, however I tried some different solutions and found one...
in custom LinearSmoothScroller I override updateActionForInterimTarget
@Override
protected void updateActionForInterimTarget(Action action) {
action.jumpTo(position);
}
It's appears not very smooth, but not instant in contrast with scrollToPositionWithOffset.
Upvotes: 4
Reputation: 1336
Take a look at hasPendingAdapterUpdates(). You can use this along with a delay() for coroutines or Thread.sleep() to enable the backing data to be available before doing the scroll.
Upvotes: 0
Reputation: 6938
If you call recyclerView.smoothScrollToPosition(pos)
will be called immediately on the UI thread
and if recyclerView
's Adapter
is too much busy to generating view items then the calling of smoothScrollToPosition
will be missed then because recyclerView
has no data to smooth scroll. So it's better to do that in a background thread by recyclerView.post()
. By calling this it goes into the Main thread
queue and gets executed after the other pending tasks are finished.
Therefore you should do something like this which worked for my case:
recyclerView.post(new Runnable() {
@Override
public void run() {
recyclerView.smoothScrollToPosition(pos);
}
});
Upvotes: 8
Reputation: 77
Just add one line for smooth scroll
recyclerView.setNestedScrollingEnabled(false);
it will work fine
Upvotes: 2