列表视图捕捉项目

我使用ListView创build图片列表,并且照片的大小适合屏幕上的2至3张照片。

我遇到的问题是,我想当用户停止滚动时,可见列表的第一项将捕捉到屏幕的顶部,例如,如果滚动结束并显示第一个图片的小部分,我们滚动列表,所以图片总是完全显示,如果大部分图片显示,我们滚动列表,所以下一张图片是完全可见的。

有没有一种方法来实现这个在Android与列表视图?

Solutions Collecting From Web of "列表视图捕捉项目"

我已经find了一种方法来做到这一点,只是听滚动和滚动结束时通过实现ListView.OnScrollListener

@Override public void onScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState) { case OnScrollListener.SCROLL_STATE_IDLE: if (scrolling){ // get first visible item View itemView = view.getChildAt(0); int top = Math.abs(itemView.getTop()); // top is a negative value int bottom = Math.abs(itemView.getBottom()); if (top >= bottom){ ((ListView)view).setSelectionFromTop(view.getFirstVisiblePosition()+1, 0); } else { ((ListView)view).setSelectionFromTop(view.getFirstVisiblePosition(), 0); } } scrolling = false; break; case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: case OnScrollListener.SCROLL_STATE_FLING: Log.i("TEST", "SCROLLING"); scrolling = true; break; } } 

变化不是那么顺利,但它的工作。

利用来自@ nininho解决scheme的一些想法,我得到了我的列表视图捕捉到一个平滑的滚动项目,而不是突然去它。 一个警告是,我只testing了一个基本的ListView与Moto X的文本解决scheme,但它在设备上工作得很好。 不过,我对这个解决scheme很有信心,并鼓励您提供反馈意见。

 listview.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // TODO Auto-generated method stub if (scrollState == SCROLL_STATE_IDLE) { View itemView = view.getChildAt(0); int top = Math.abs(itemView.getTop()); int bottom = Math.abs(itemView.getBottom()); int scrollBy = top >= bottom ? bottom : -top; if (scrollBy == 0) { return; } smoothScrollDeferred(scrollBy, (ListView)view); } } private void smoothScrollDeferred(final int scrollByF, final ListView viewF) { final Handler h = new Handler(); h.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub viewF.smoothScrollBy(scrollByF, 200); } }); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // TODO Auto-generated method stub } }); 

我推迟平滑滚动的原因是因为在我的testing中,直接调用状态改变callback中的smoothScrollBy方法实际上是滚动问题。 另外,我也没有预见到一个经过充分testing的,强大的解决scheme,并且在我的解决scheme中,我根本没有任何状态。 这个解决scheme还没有在Google Play商店中,但应该是一个很好的起点。

使用@nininho的解决scheme,

在状态更改为SCROLL_STATE_IDLE时的onScrollStateChanged ,记住要捕捉的位置并引发一个标志:

 snapTo = view.getFirstVisiblePosition(); shouldSnap = true; 

然后,重写computeScroll()方法:

 @Override public void computeScroll() { super.computeScroll(); if(shouldSnap){ this.smoothScrollToPositionFromTop(snapTo, 0); shouldSnap = false; } } 

如果你使用RecyclerView,你可以做更平滑的滚动。 OnScrollListener更好。

我在这里做了一个例子: https : //github.com/plattysoft/SnappingList

除了尝试上面的代码,你应该确保你的listView有一个高度,可以适合你想要显示的项目的确切数量。 例如,如果要在捕捉效果之后显示4个项目,并且您的行高(在其布局中定义)应该是列表总高度的1/4。

请注意,在调用smoothScrollBy()之后, getFirstVisiblePosition()可能会指向列表视图中最顶层的列表项。 当view.getChildAt(0).getBottom() == 0时尤其如此。 我不得不调用view.setSelection(view.getFirstVisiblePosition() + 1)来纠正这种奇怪的行为。