|
基于ScrollView反弹效果的一些原理(可以看我另外一篇帖子),看了下ListView滚动的一些代码.发现这两者实现方式有些不太一样.
ListView根本没有继承使用View的ScrollBy和ScrollTo,而且它的移动到最上和最下的判断也打不一样,代码如下,截取自AbstractListView的trackMotionScroll(int,int)方法:
final int end = getHeight() - listPadding.bottom;
final int spaceBelow = lastBottom - end;
final int height = getHeight() - mPaddingBottom - mPaddingTop;
if (deltaY < 0) {
deltaY = Math.max(-(height - 1), deltaY);
} else {
deltaY = Math.min(height - 1, deltaY);
}
if (incrementalDeltaY < 0) {
incrementalDeltaY = Math.max(-(height - 1), incrementalDeltaY);
} else {
incrementalDeltaY = Math.min(height - 1, incrementalDeltaY);
}
final int firstPosition = mFirstPosition;
if (firstPosition == 0 && firstTop >= listPadding.top && deltaY >= 0) {
// Don't need to move views down if the top of the first position
// is already visible
return true;
}
if (firstPosition + childCount == mItemCount && lastBottom <= end && deltaY <= 0) {
// Don't need to move views up if the bottom of the last position
// is already visible
return true;
}
这个mFirstPosition是显示的第一个ListView的Item,firstPosition + childCount == mItemCount这句话的意思是可以显示最后的childCount条(这是个规律,自己可以算算),在加上lastBottom(也就是最后一个显示item)比end(也就是ListView的最底部距离最上部的距离)小,一般情况下都是比它大,如图:
,firstTop >= listPadding.top 和这个相反,也就是第一个item比paddingTop要大,如果ListView不设这个属性的话那就是0了.这里要说下不管是end、firstTop或者是lastBottom意思都是距离它的最上面的组件或者是parent的距离,不是屏幕.详细的大家可以去看trackMotionScroll.
我的实现是在基本不破坏原有功能的基础上加入了一些可以继续移动的代码,也就是使用View的scrollBy.
此为抛砖引玉,反弹效果刷新实现有点生硬,大家可以优化它,让它更流畅。 |
|