android: smoothScrollToPosition() not working correctly android: smoothScrollToPosition() not working correctly android android

android: smoothScrollToPosition() not working correctly


You probably want to tell the ListView to post the scroll when the UI thread can handle it (which is why yours it not scrolling properly). SmoothScroll needs to do a lot of work, as opposed to just go to a position ignoring velocity/time/etc. (required for an "animation").

Therefore you should do something like:

    getListView().post(new Runnable() {        @Override        public void run() {            getListView().smoothScrollToPosition(pos);        }    });


(Copied from my answer: smoothScrollToPositionFromTop() is not always working like it should)

This is a known bug. See https://code.google.com/p/android/issues/detail?id=36062

However, I implemented this workaround that deals with all edge cases that might occur:

First call smothScrollToPositionFromTop(position) and then, when scrolling has finished, call setSelection(position). The latter call corrects the incomplete scrolling by jumping directly to the desired position. Doing so the user still has the impression that it is being animation-scrolled to this position.

I implemented this workaround within two helper methods:

smoothScrollToPosition()

public static void smoothScrollToPosition(final AbsListView view, final int position) {    View child = getChildAtPosition(view, position);    // There's no need to scroll if child is already at top or view is already scrolled to its end    if ((child != null) && ((child.getTop() == 0) || ((child.getTop() > 0) && !view.canScrollVertically(1)))) {        return;    }    view.setOnScrollListener(new AbsListView.OnScrollListener() {        @Override        public void onScrollStateChanged(final AbsListView view, final int scrollState) {            if (scrollState == SCROLL_STATE_IDLE) {                view.setOnScrollListener(null);                // Fix for scrolling bug                new Handler().post(new Runnable() {                    @Override                    public void run() {                        view.setSelection(position);                    }                });            }        }        @Override        public void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount,                                 final int totalItemCount) { }    });    // Perform scrolling to position    new Handler().post(new Runnable() {        @Override        public void run() {            view.smoothScrollToPositionFromTop(position, 0);        }    });}

getChildAtPosition()

public static View getChildAtPosition(final AdapterView view, final int position) {    final int index = position - view.getFirstVisiblePosition();    if ((index >= 0) && (index < view.getChildCount())) {        return view.getChildAt(index);    } else {        return null;    }}