smoothScrollToPositionFromTop()并不总是工作像它应该并不、工作、smoothScrollToPositionFromTop

2023-09-12 08:40:17 作者:最后一分随心所欲

我一直在尝试了一段时间,以获得smoothScrollToPositionFromTop()的工作,但它并不总是滚动到正确的位置。

I've been trying for a while to get smoothScrollToPositionFromTop() working, but it doesn't always scroll to the correct position.

我有一个ListView(10个项目)与上侧10个按钮的布局,这样我就可以滚动到列表中的每个项目。通常,当我滚动一个位置向后或向前它工作正常,但往往当我尝试滚动3个以上的位置向后或向前ListView控件不完全结束在所选位置。当它失败时,它通常结束了0,5 1,5项关闭,它是不是真的predictable当滚动失败。

I've got a ListView (with 10 items) in a layout with 10 buttons on the side, so I can scroll to every item in the list. Usually when I scroll one position back or forward it works fine, but often when I try to scroll more then 3 positions back or forward the ListView does not exactly end at the selected position. When it fails, it usually ends up 0,5 to 1,5 items off and it is not really predictable when the scroll fails.

我还检查了smoothScrollToPosition notifyDataSetChanged后不工作在Android的,但这种修复工作不适合我,我不会改变任何数据。

I have also checked out smoothScrollToPosition after notifyDataSetChanged not working in android, but this fix is not working for me and I don't change any data.

我真的想自动滚动到选定的listItems中的,但不是我想不出如何。有没有人收到这个问题,并知道如何解决它?

I would really like to automatically scroll to the selected listitems, but not I can't figure out how. Has anybody had this problem before and knows how to fix it?

推荐答案

这是一个已知的bug。请参见的https://$c$c.google.com/ P /安卓/问题/详细信息?ID = 36062

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:

第一次调用 smothScrollToPositionFromTop(位置),然后当滚动完成后,叫 setSelection(位置)。后者呼吁通过直接跳转到所需位置校正不完全滚动。这样做的用户仍可以在IM pression它被动画滚动到这个位置。

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:

smoothScrollToPositionFromTop()

public static void smoothScrollToPositionFromTop(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;
    }
}