Android ListView记录和恢复滑动位置

有时在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的滚动高度。


猜你喜欢

转载自blog.csdn.net/wangsf1112/article/details/73277605