android:smoothScrollToPosition()不能正常工作

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

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

你可能想告诉ListView在UI线程可以处理它时发布滚动(这就是为什么你不滚动正确)。 SmoothScroll需要做很多工作,而不是去忽略velocity / time /等的位置。 (需要“animation”)。

所以你应该做这样的事情:

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

(从我的答案复制: smoothScrollToPositionFromTop()并不总是像它应该 )

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

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

首先调用smothScrollToPositionFromTop(position) ,然后当滚动完成时,调用setSelection(position) 。 后者通过直接跳转到所需的位置来纠正不完整的滚动。 这样做的用户仍然有这样的印象,即正在被animation滚动到这个位置。

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

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

你应该使用setSelection()方法。

Lars提到的设置select方法是有效的,但是对于我们的目的而言,animation太过分了,因为它会跳过剩下的东西。 另一个解决scheme是重复调用该方法,直到第一个可见的位置是您的索引。 这是最好的快速完成,并有一个限制,因为它将打击用户滚动视图,否则。

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

解决scheme是在C#通过。 Xamarin,但应该很容易翻译成Java。

在你调用arrayadapter.notifyDataSetChanged()之后你调用arrayadapter.add()吗? 另外可以肯定的是, smoothScrollToPositionsetSelectionListView可用方法,而不是上面提到的arrayadapter

在任何情况下,看看是否有帮助: notifyDataSetChanged之后的smoothScrollToPosition不工作在Android中

 final Handler handler = new Handler(); //100ms wait to scroll to item after applying changes handler.postDelayed(new Runnable() { @Override public void run() { listView.smoothScrollToPosition(selectedPosition); }}, 100);