有时候实现比较好的用户体验,需要保持当前的ListView的位置。换句话说,我们想要随心所欲地指定ListView滚动的位置,在ListView中,有一个setSelectionFromTop ()方法。
下面是一个使用范例。代码如下:
// save index and top position
int index = mList.getFirstVisiblePosition();
View v = mList.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
mList.setSelectionFromTop(index, top);
注解: ListView.setSelectionFromTop(int position, int y);其中position指的是指定的item的在ListView中的索引, 注意如果有Header存在的情况下,索引是从Header就开始算的。y指的是到ListView可见范围内最上边边缘的距离。
ListView.getChildAt(int position), 这个position指的是在可视的item中的索引,跟cursor里的位置是大不一样的。 可以看看ListView.getChildCount()函数得到个数是小于或等于Cursor里的个数的(不考虑header的话)。 虽然一共可能有20条数据,但是界面只能看到8条,那么这个ChildCount大约就是8了。 另一方面, FirstVisiblePosition取出的是第一个可见的item在总的条数中的索引,再将会消失的header考虑进来
看一下setSelectionFromTop()的具体实现,代码如下:
public void setSelectionFromTop(int position, int y) {
if (mAdapter == null) {
return;
}
if (!isInTouchMode()) {
position = lookForSelectablePosition(position, true);
if (position >= 0) {
setNextSelectedPositionInt(position);
}
} else {
mResurrectToPosition = position;
}
if (position >= 0) {
mLayoutMode = LAYOUT_SPECIFIC;
mSpecificTop = mListPadding.top + y;
if (mNeedSync) {
mSyncPosition = position;
mSyncRowId = mAdapter.getItemId(position);
}
if (mPositionScroller != null) {
mPositionScroller.stop();
}
requestLayout();
}
}
从上面的代码可以得知,setSelectionFromTop()的作用是设置ListView选中的位置,同时在Y轴设置一个偏移量(padding值)。 ListView还有一个方法叫setSelection(),传入一个index整型数值,就可以让ListView定位到指定Item的位置。 这两个方法有什么区别呢?看一下setSelection()的具体实现,代码如下:
@Override
public void setSelection(int position) {
setSelectionFromTop(position, 0);
}
原来,setSelection()内部就是调用了setSelectionFromTop(),只不过是Y轴的偏移量是0而已。 现在应该对setSelection()和setSelectionFromTop()有了更深刻的认识了。
另外,可以通过别的方式可以记录listView滚动到的位置的坐标,然后利用listView.scrollTo精确的进行恢复 。
listView.setOnScrollListener(new OnScrollListener() {
/** * 滚动状态改变时调用 */
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// 不滚动时保存当前滚动到的位置
if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {
if (currentMenuInfo != null) {
scrolledX = statusListView.getScrollX();
scrolledY = statusListView.getScrollY();
}
}
}
/** * 滚动时调用 */
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
});
在恢复位置时调用
listView.scrollTo(scrolledX, scrolledY);