在开发过程中,可能需要获取ListView的垂直滚动距离,通过滚动距离,来做一些UI上的变化。在ListView的OnScrollListener监听器中,只提供了第一个可见Item的位置(firstVisibleItem)、可见Item的总数(visibleItemCount)以及Item的总数(totalItemCount),并没有提供直接获取垂直滚动距离的方法,这时需要自己通过这些参数来计算ListView垂直滚动距离。
说一下具体实现的思路:
(1)监听ListView的滚动事件,在onScroll方法中,首先将当前第一个可见Item的高度和top存入到SparseArray中。
(2)然后在获取垂直滚动距离时,从SparseArray中取出所有被滑动隐藏的Item的高度相加,即得到了被滑动隐藏掉的Item的高度总和。
(3)最后用高度总和加上当前第一个可见Item的top值,该top值就是当前第一个可见Item被滑动隐藏掉的高度,这样就得到了ListView垂直滚动的距离。具体实现代码如下所示:
mListView.setOnScrollListener(new OnScrollListener() {
// 创建一个稀疏数组,用于存储Item的高度和mTop
private SparseArray recordSp = new SparseArray(0);
private int mCurrentFirstVisibleItem = 0;
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
mCurrentFirstVisibleItem = firstVisibleItem;
// 这里获取的Item是ListView中第一个可见的Item
View firstView = view.getChildAt(0);
if (null != firstView) {
ItemRecord itemRecord =
(ItemRecord) recordSp.get(firstVisibleItem);
if (null == itemRecord) {
itemRecord = new ItemRecord();
}
itemRecord.height = firstView.getHeight();
// top值总是小于或等于0的
itemRecord.top = firstView.getTop();
/**
* 将当前第一个可见Item的高度和top存入SparseArray中,
* SparseArray的key是Item的position
*/
recordSp.append(firstVisibleItem, itemRecord);
int scrollY = getScrollY();
Log.i(TAG, "垂直滚动距离:" + scrollY);
}
}
private int getScrollY() {
int height = 0;
for (int i = 0; i < mCurrentFirstVisibleItem; i++) {
/**
* 取出所有已滑过的Item的高度,相加。
* 说明下这里为什么不直接用一个Item高度乘以所有已滑过的Item的数量,
* 主要是考虑到可能为ListView添加Header这种情况,如果Header的高度
* 与Item的高度是相同的可以这样做,如果Header的高度不等于Item的高度,
* 这时将Header的高度直接按照Item的高度来计算就不准确了。
*/
ItemRecord itemRecord = (ItemRecord) recordSp.get(i);
height += itemRecord.height;
}
//取出当前第一个可见Item的ItemRecord对象
ItemRecord itemRecord =
(ItemRecord) recordSp.get(mCurrentFirstVisibleItem);
if (null == itemRecord) {
itemRecord = new ItemRecord();
}
//由于存入的top值是小于或等于0的,这里是减去top值而不是加
return height - itemRecord.top;
}
class ItemRecord {
int height = 0;
int top = 0;
}
});