android: smoothScrollToPosition() not working correctly

后端 未结 7 2108
心在旅途
心在旅途 2020-12-03 00:11

I\'m trying to smoothly scroll to last element of a list after adding an element to the arrayadapter associated with the listview. The problem is that it just scrolls to a r

7条回答
  •  南方客
    南方客 (楼主)
    2020-12-03 00:55

    (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;
        }
    }
    

提交回复
热议问题