SamIAmHarris
SamIAmHarris

Reputation: 2178

Smooth Scroll Not Working on Initial Scroll for Android RecyclerView

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

Answers (4)

Natalie Kukharchyk
Natalie Kukharchyk

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

Clocker
Clocker

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

Gk Mohammad Emon
Gk Mohammad Emon

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

shoaib soudagar
shoaib soudagar

Reputation: 77

Just add one line for smooth scroll

recyclerView.setNestedScrollingEnabled(false);

it will work fine

Upvotes: 2

Related Questions