有时在Activity或view切换时,需要恢复listView之前滚动到的位置。
在ListView停止滑动后记录滑动到的位置:
int scrollPos;
int scrollTop;
listview.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override public void onScrollStateChanged(AbsListView view, int scrollState) { Log.d(TAG, "OnScrollListener scrollState:" + scrollState + " totalCount:" + totalCount + " lastVisibleIndex:" + lastVisibleIndex); switch (scrollState) { case AbsListView.OnScrollListener.SCROLL_STATE_IDLE: scrollPos = listview.getFirstVisiblePosition();View viewItem = listview.getChildAt(0); scrollTop = viewItem == null ? 0 : viewItem.getTop();break;
case AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
case AbsListView.OnScrollListener.SCROLL_STATE_FLING:
break;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
firstVisible = firstVisibleItem;
visibleCount = visibleItemCount;
totalCount = totalItemCount;
lastVisibleIndex = firstVisibleItem + visibleItemCount - 1;
}
});
恢复滑动到的位置:
listview.setSelectionFromTop(scrollPos, scrollTop);
或者 只是恢复到具体Item的开始位置:
listview.setSelection(scrollPos);
----------------------------------------------分割线-----------------------------------------------------
但是,现在网上搜索出来的经常会有以下方法:
记录listView滚动到的位置的坐标,然后利用listView.scrollTo精确的进行恢复
listView.setOnScrollListener(new OnScrollListener() { /** * 滚动状态改变时调用 */ @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // 停止滚动时保存当前滚动到的位置 if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) { scrolledX = listView.getScrollX(); scrolledY = listView.getScrollY(); } } /** * 滚动时调用 */ @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { } });
在恢复位置时调用:
listView.scrollTo(scrolledX, scrolledY);
可以使用listView.scrollTo(x, y)滚动到某个位置。
网上的这个方式简直就是个坑!通过实际验证发现ListView滚动距离通过listView.getScrollX()和listView.getScrollY()方法返回的值都是0。经过查找资料和源码发现getScrollX()、getScrollY()是作用于view上的而不是ListView上的。
/** * Return the scrolled top position of this view. This is the top edge of * the displayed part of your view. You do not need to draw any pixels above * it, since those are outside of the frame of your view on screen. * * @return The top edge of the displayed part of your view, in pixels. */ public final int getScrollY() { return mScrollY; }
ListView没有提供得到滚动高度的任何方法,但是可以自己根据listView.
getChildAt(0).getTop()
和listView.
getFirstVisiblePosition()
来综合计算获得:
public int getScrollY() { View c = listview.getChildAt(0); //获取当前可见区域的第一个Item if (c == null) { return 0; } int firstVisiblePosition = listview.getFirstVisiblePosition(); int top = c.getTop(); return firstVisiblePosition * c.getHeight() - top; }
上述方法是在假设每个item的高度是固定的情况(多数情况下的确如此),只要知道当前在第几个item,就可以计算出总的高度,因为第一个可见item可能只显示了一部分出来,所以再通过listView.getChildAt(0)获得第一个子view,使用
getTop()方法计算出这个偏差。综合起来就可以计算出当前ListView的滚动高度。