android:smoothScrollToPosition()无法正常工作

时间:2012-07-11 11:38:38

标签: android listview selection android-arrayadapter smooth-scrolling

在将一个元素添加到与listview关联的arrayadapter之后,我正在尝试平滑地滚动到列表的最后一个元素。 问题是它只是滚动到一个随机位置

arrayadapter.add(item);
//DOES NOT WORK CORRECTLY:
listview.smoothScrollToPosition(arrayadapter.getCount()-1);

//WORKS JUST FINE:
listview.setSelection(arrayadapter.getCount()-1);

8 个答案:

答案 0 :(得分:55)

您可能希望告诉ListView在UI线程可以处理它时发布滚动(这就是为什么它不能正确滚动)。 SmoothScroll需要做很多工作,而不是只是去一个忽略速度/时间/等的位置。 (“动画”所需)。

因此,您应该执行以下操作:

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

答案 1 :(得分:12)

(从我的回答中复制:smoothScrollToPositionFromTop() is not always working like it should

这是一个已知错误。请参阅https://code.google.com/p/android/issues/detail?id=36062

但是,我实施了此解决方法,处理可能发生的所有边缘情况:

首先调用smothScrollToPositionFromTop(position),然后在滚动完成后,调用setSelection(position)。后一个调用通过直接跳到所需位置来纠正不完整的滚动。这样做,用户仍然会感觉它正在动画滚动到此位置。

我在两个辅助方法中实现了这个解决方法:

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

答案 2 :(得分:6)

您应该使用setSelection()方法。

答案 3 :(得分:3)

Lars提到的集合选择方法有效,但动画对于我们的目的来说太过于跳跃,因为它会跳过剩下的东西。另一种解决方案是重复调用该方法,直到第一个可见位置为您的索引。这是最好的快速和限制,因为它将打击用户滚动视图否则。

private  void DeterminedScrollTo(Android.Widget.ListView listView, int index, int attempts = 0) {
    if (listView.FirstVisiblePosition != index && attempts < 10) {
        attempts++;
        listView.SmoothScrollToPositionFromTop (index, 1, 100);
        listView.PostDelayed (() => {
            DeterminedScrollTo (listView, index, attempts);
        }, 100);
    }
}

解决方案是在C#中。 Xamarin但应该很容易转换为Java。

答案 4 :(得分:2)

np.array(g).astype(np.float64)

答案 5 :(得分:2)

使用LayoutManager平滑滚动

layoutManager.smoothScrollToPosition(recyclerView, new RecyclerView.State(), position);

答案 6 :(得分:1)

致电arrayadapter.notifyDataSetChanged()后,您是否致电arrayadapter.add()?另外可以肯定的是,smoothScrollToPositionsetSelectionListView而非arrayadapter中可用的方法,如上所述。

无论如何,看看这是否有帮助: smoothScrollToPosition after notifyDataSetChanged not working in android

答案 7 :(得分:0)

在android java中使用它,它对我有用:

private void DeterminedScrollTo(int index, int attempts) {
        if (listView.getFirstVisiblePosition() != index && attempts < 10) {
            attempts++;
            if (listView.canScrollVertically(pos))
                listView.smoothScrollToPositionFromTop(index, 1, 200);
            int finalAttempts = attempts;
            new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                @Override
                public void run() {
                    DeterminedScrollTo(index, finalAttempts);
                }
            }, 200);
        }
    }