Android:别让ListView的各种scroll迷失了

Posted bdmh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android:别让ListView的各种scroll迷失了相关的知识,希望对你有一定的参考价值。

目录

 

scrollTo(View.java):不建议使用

scrollBy(View.java):

setSelectionFromTop(AbsListView.java);

setSelection:(ListView.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内部的一些属性,比如getLastVisiblePositiongetFirstVisiblePosition等。因此如果通过此方法进行滚动后,访问一些索引属性时,特别需要注意。

执行下面代码的效果如图:顶部会空出一块。整个画布下移。

listView.scrollTo(0,-500);

如果scrollTo之后,调用setSelection方法,这个空白是不会消失的,比如我有100条数据,我要选中最后一条(索引为99),先scrollTosetSelection,结果如图:最后一条并未出现在视野中,因为整个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);

这个方法会影响getLastVisiblePositiongetFirstVisiblePosition等属性。

注意点:这个方法会把选中的item放到第一条,也就是getFirstVisiblePosition的值会改变为Position参数值。但是如果position的位置已经不能支撑Listview滚动到顶部时,就会是这个样子:比如我要选中最后一条(索引99)。

listView.setSelectionFromTop(99,0);

我们想象的是,最后一条会出现在最顶端,但是如果这样的话,那么listview岂不是除了这一条item之外,其余都是空白了吗,这样肯定是不行的,所以结果如图:同时也会影响getLastVisiblePositiongetFirstVisiblePosition等属性。

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调用trackMotionScrolltrackMotionScroll会判断手指滑动方向,然后调用ListViewfillGap方法,进而调用fillDownfillUp填充视图。会影响getLastVisiblePositiongetFirstVisiblePosition等属性。

特别注意:如果想滚动到某一条,然后再偏移一定的距离,如果你是如下代码:

listView.setSelectionFromTop(99,0);
listView.scrollListBy(-500);

两行代码连续执行,这个是不能实现的。setSelectionFromTop会出发ViewrequestLayout,进而通过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迷失了的主要内容,如果未能解决你的问题,请参考以下文章

Android ListView常见配置说明

如何清空android ListView控件的内容

2Android-UI(自定义控件&ListView)

七夕活动浪漫上线,别让网络拖慢和小姐姐的开黑时间

Android UI:ListView -- SimpleAdapter

Android新手入门2016--ListView之ArrayAdapter