Android ListView记录和恢复滑动位置

来源:互联网 发布:梵高色盲知乎 编辑:程序博客网 时间:2024/05/24 00:50
有时在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的滚动高度。