在体验其他设计优美的app时加载动画的假象让我以为Listview的最后一条item完全显示之后才正式加载,导致我走入了一个误区浪费了很长的一段时间,最终我也是妥协以最后一条item刚被暴露开始作为Listview滚动到底部的标志,也就是说无须费很大劲去实现一个并没有多大提升的细节了。期间当然发现了一些很好的解决办法,
其一(网上引用的代码,原始出处不详,故不注明了):
1 private int getLastVisiblePosition = 0, lastVisiblePositionY = 0;
2
3 friendsTimeLineMsgList.setOnScrollListener(new AbsListView.OnScrollListener() {
4 boolean isLastRow = false;
5 @Override
6 public void onScrollStateChanged(AbsListView absListView, int scrollState) {
7 if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
8 if (absListView.getLastVisiblePosition() == (absListView.getCount() - 1)) {
9 Log.i(TAG, "scroll to bottom");
10
11 View v = (View) absListView.getChildAt(absListView.getChildCount() - 1);
12 int[] location = new int[2];
13 v.getLocationOnScreen(location);//获取在整个屏幕内的绝对坐标
14 int y = location[1];
15 Log.e("x" + location[0], "y" + location[1]);
16 if (absListView.getLastVisiblePosition() != getLastVisiblePosition
17 && lastVisiblePositionY != y) {
18 //第一次拖至底部
19 Toast.makeText(absListView.getContext(), "再次拖至底部,即可翻页", Toast.LENGTH_SHORT).show();
20 getLastVisiblePosition = absListView.getLastVisiblePosition();
21 lastVisiblePositionY = y;
22 return;
23 } else if (absListView.getLastVisiblePosition() == getLastVisiblePosition
24 && lastVisiblePositionY == y) {
25 //第二次拖至底部
26 Toast.makeText(absListView.getContext(), "已经至底部", Toast.LENGTH_SHORT).show();
27 }
28 }
29 //未滚动到底部,第二次拖至底部都初始化
30 getLastVisiblePosition = 0;
31 lastVisiblePositionY = 0;
32 }
33
34 }
35 }
简而言之,这种办法就是判断第二次向上滑动时item的位置有没有变化,没有变化就说明已经到底了。很好的实现,也在一些app上看到过,并且做了一个橡皮筋类似ios下拉刷新那样的一个优化,但是对于android来说,个人不仅不认同橡皮筋似的下拉刷新,另外这种需要人为去加载感觉并不是一个很好的方法,所以直接放弃了。
其二(原始链接):
private int preLast;
// Initialization stuff.
yourListView.setOnScrollListener(this);// ... ... ...
@Override
public void onScroll(AbsListView lw, final int firstVisibleItem,
final int visibleItemCount, final int totalItemCount) {switch(lw.getId()) {
case android.R.id.list:// Make your calculation stuff here. You have all your
// needed info from the parameters of this function.// Sample calculation to determine if the last
// item is fully visible.
final int lastItem = firstVisibleItem + visibleItemCount;
if(lastItem == totalItemCount) {
if(preLast!=lastItem){ //to avoid multiple calls for last item
Log.d("Last", "Last");
preLast = lastItem;
}
}
}
}
我不知道为什么原作者加上那么一句“判断最后一个item完全可见的计算方法”,很明显,这只能避免多次被调用,所以到这里的时候我感觉要放弃了,然后去看了两集唐顿回来再拿其他的app把玩,发现是自己逼自己走上那么一个误区。哪怕最后一个item才刚露出来就去加载下一分页的内容其实也没多少消耗反而提升了用户体验吧,无需长时等待,这也是方法一不好的那方面。所以最后对代码再加以简单的修改,增加一个滚动停止的判断:
1 friendsTimeLineMsgList.setOnScrollListener(new AbsListView.OnScrollListener() {
2 boolean isLastRow = false;
3 @Override
4 public void onScrollStateChanged(AbsListView absListView, int scrollState) {
5 if (isLastRow && scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
6 //加载元素
7 isLastRow = false;
8 // Toast.makeText(absListView.getContext(), "bottom", Toast.LENGTH_SHORT).show();
9 }
10
11 }
12
13 //滚动时一直回调,直到停止滚动时才停止回调。单击时回调一次。
14 //firstVisibleItem:当前能看见的第一个列表项ID(从0开始)
15 //visibleItemCount:当前能看见的列表项个数(小半个也算)
16 //totalItemCount:列表项共数
17 @Override
18 public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
19 switch (absListView.getId()) {
20 case R.id.friends_timeline_msglist:
27
28 final int lastItem = firstVisibleItem + visibleItemCount;
29 if (lastItem == totalItemCount) {
30 if (preLast != lastItem) { //to avoid multiple calls for last item
31 Log.d("Last", "Last");
32 showFooterView();
33 preLast = lastItem;
34 isLastRow = true;
35 }
36 }
37 }
38 }
39 });
这样可以保证在最后一个item可见但还没有停止滚动的时候是无法加载下一页的,稍微满足一下强迫症吧。忘了说,后来给Listview加了个footerView。
有关Listview分页以及判断Listview是否已经滚动到低端的一些探索,布布扣,bubuko.com