Android:别让ListView的各种scroll迷失了
Posted bdmh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android:别让ListView的各种scroll迷失了相关的知识,希望对你有一定的参考价值。
目录
setSelectionFromTop(AbsListView.java);
scrollListBy(AbsListView.java):
scrollTo(View.java):不建议使用
这个滚动是滚动的View的位置,并不是ListView内部的Item滚动,它是通过改变mScrollX或mScrollY的值,通过画布的translate来改变视图位置的。
public void scrollTo(int x, int y)
if (mScrollX != x || mScrollY != y)
......
mScrollY = y;
......
然后通过调用View的updateDisplayListIfDirty方法,进行canvas的转换。
public RenderNode updateDisplayListIfDirty()
......
canvas.translate(-mScrollX, -mScrollY);
......
所以使用这个方法时,并不影响ListView内部的一些属性,比如getLastVisiblePosition、getFirstVisiblePosition等。因此如果通过此方法进行滚动后,访问一些索引属性时,特别需要注意。
执行下面代码的效果如图:顶部会空出一块。整个画布下移。
listView.scrollTo(0,-500);
如果scrollTo之后,调用setSelection方法,这个空白是不会消失的,比如我有100条数据,我要选中最后一条(索引为99),先scrollTo再setSelection,结果如图:最后一条并未出现在视野中,因为整个View视图向下移动了500像素,所以看不到。
scrollBy(View.java):
这个比较好理解,看代码就知道啦,内部就是调用scrollTo,参数代表的是在原基础上继续偏移,不多讲。
public void scrollBy(int x, int y)
scrollTo(mScrollX + x, mScrollY + y);
setSelectionFromTop(AbsListView.java);
public void setSelectionFromTop(int position, int y)
从名字可以看出,这个方法是从ListView的顶部开始,选中指定索引的item,并且在Y轴上偏移指定的值(包括ListView的Padding),y<0,向上走一点,y>0,向下走一点。
如下面的代码:选中索引为10的item,然后向上偏移30像素。我没看到item被盖住了一部分。
listView.setSelectionFromTop(10,-30);
这个方法会影响getLastVisiblePosition、getFirstVisiblePosition等属性。
注意点:这个方法会把选中的item放到第一条,也就是getFirstVisiblePosition的值会改变为Position参数值。但是如果position的位置已经不能支撑Listview滚动到顶部时,就会是这个样子:比如我要选中最后一条(索引99)。
listView.setSelectionFromTop(99,0);
我们想象的是,最后一条会出现在最顶端,但是如果这样的话,那么listview岂不是除了这一条item之外,其余都是空白了吗,这样肯定是不行的,所以结果如图:同时也会影响getLastVisiblePosition、getFirstVisiblePosition等属性。
setSelection:(ListView.java)
public void setSelection(int position)
setSelectionFromTop(position, 0);
内部使用setSelectionFromTop,偏移为0,不说了。
scrollListBy(AbsListView.java):
这个方法是用来滚动ListView内部item视图的,相比scrollTo,建议使用scrollListBy。需要API>=19。该方法,每执行一次,就会滚动一次,直到滚动了。
同时为了配合这个方法,android还提供了canScrollList方法用来判断是否可以滚动列表。
public void scrollListBy(int y)
trackMotionScroll(-y, -y);
scrollListBy调用trackMotionScroll,trackMotionScroll会判断手指滑动方向,然后调用ListView的fillGap方法,进而调用fillDown或fillUp填充视图。会影响getLastVisiblePosition、getFirstVisiblePosition等属性。
特别注意:如果想滚动到某一条,然后再偏移一定的距离,如果你是如下代码:
listView.setSelectionFromTop(99,0);
listView.scrollListBy(-500);
两行代码连续执行,这个是不能实现的。setSelectionFromTop会出发View的requestLayout,进而通过ViewRootImpl中的scheduleTraversals,执行线程mTraversalRunnable。
void scheduleTraversals()
if (!mTraversalScheduled)
......
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
......
scrollListBy中的偏移,需要使用内部属性mFirstPosition来判断是否可以上下滚动,而mFirstPosition是在setSelectionFromTop被改变的,但由于setSelectionFromTop中使用了线程,不能保证线程的回调在scrollListBy执行时已经执行完毕,当scrollListBy执行时,mFirstPosition并未改变,所以是无法滚动的。
以上是关于Android:别让ListView的各种scroll迷失了的主要内容,如果未能解决你的问题,请参考以下文章