在Android中按像素滚动ListView

我想通过像素数在Android中滚动ListView 。 例如,我想滚动列表向下10个像素(以便列表中的第一个项目的前10个像素行被隐藏)。

我以为在ListView上显然可见的scrollByscrollTo方法会做这个工作,但他们不这样做,而是他们错误地滚动整个列表(实际上,即使我已经用我的手指滚动列表, getScrollY总是返回零)。

我正在做的是捕捉轨迹球事件,我想根据轨迹球的运动顺利地滚动列表视图。

Solutions Collecting From Web of "在Android中按像素滚动ListView"

支持滚动ListView小部件的方式是:

mListView.smoothScrollToPosition(position);

http://developer.android.com/reference/android/widget/AbsListView.html#smoothScrollToPosition(int)

但是,由于您具体提到要垂直偏移视图,您必须调用:

mListView.setSelectionFromTop(position, yOffset);

http://developer.android.com/reference/android/widget/ListView.html#setSelectionFromTop(int,%20int)

请注意,您也可以使用smoothScrollByOffset(yOffset) 。 但是只有API> = 11才支持

http://developer.android.com/reference/android/widget/ListView.html#smoothScrollByOffset(int)

如果您查看在api 19中添加的scrollListBy()方法的源代码,您将看到可以使用软件包作用域trackMotionScroll方法。

 public class FutureListView { private final ListView mView; public FutureListView(ListView view) { mView = view; } /** * Scrolls the list items within the view by a specified number of pixels. * * @param y the amount of pixels to scroll by vertically */ public void scrollListBy(int y) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { mView.scrollListBy(y); } else { // scrollListBy just calls trackMotionScroll trackMotionScroll(-y, -y); } } private void trackMotionScroll(int deltaY, int incrementalDeltaY) { try { Method method = AbsListView.class.getDeclaredMethod("trackMotionScroll", int.class, int.class); method.setAccessible(true); method.invoke(mView, deltaY, incrementalDeltaY); } catch (Exception ex) { throw new RuntimeException(ex); }; } } 

这里是我的ListView子类的一些代码。 它可以很容易地适应,所以它可以在活动代码中使用。

getListItemsHeight()返回列表的总像素高度,并填充每个项目的垂直像素偏移量的数组。 当此信息有效时, getListScrollY()返回当前的垂直像素滚动位置,而scrollListToY()将列表滚动到像素位置。 如果列表的大小或内容发生更改, getListItemsHeight()必须再次调用getListItemsHeight()

 private int m_nItemCount; private int[] m_nItemOffY; private int getListItemsHeight() { ListAdapter adapter = getAdapter(); m_nItemCount = adapter.getCount(); int height = 0; int i; m_nItemOffY = new int[m_nItemCount]; for(i = 0; i< m_nItemCount; ++i){ View view = adapter.getView(i, null, this); view.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); m_nItemOffY[i] = height; height += view.getMeasuredHeight(); } return height; } private int getListScrollY() { int pos, nScrollY, nItemY; View view; pos = getFirstVisiblePosition(); view = getChildAt(0); nItemY = view.getTop(); nScrollY = m_nItemOffY[pos] - nItemY; return nScrollY; } private void scrollListToY(int nScrollY) { int i, off; for(i = 0; i < m_nItemCount; ++i){ off = m_nItemOffY[i] - nScrollY; if(off >= 0){ setSelectionFromTop(i, off); break; } } } 

现在,ListViewCompat可能是一个更好的解决scheme。

 android.support.v4.widget.ListViewCompat.scrollListBy(@NonNull ListView listView, int y) 

如果你想要像素移动,那么你可以使用这个

 public void scrollBy(ListView l, int px){ l.setSelectionFromTop(l.getFirstVisiblePosition(),l.getChildAt(0).getTop() - px); } 

这适用于甚至有大量标题的人