android listview 计算滑动距离

来源:互联网 发布:ug软件代理 编辑:程序博客网 时间:2024/05/17 07:53

原理解析:

首先,将listview的滑动过程抽象成n帧画面,每一帧都对应一个时间点,且会回调onScroll方法。相邻的两帧之间的关系,有以下三种关系:

1.firstVisible view没有变化。 如上一帧 与 下一帧的firstVisible view 都是view2,。计算出两帧之间的距离

2.firstVisible view发生变化,且是向上滑的情况。如上一帧的firstVisible view 是view2 , 下一帧的 firstVisible view 是 view3 。计算出两帧之间的距离

3.firstVisible view发生变化,且是向下滑的情况。如上一帧的firstVisible view 是view2 , 下一帧的 firstVisible view 是 view1 。计算出两帧之间的距离

如此,我们便算出相邻时间点之间的移动距离,再将它们累加起来便是listview的滑动距离。


代码片段:

public class MyListView extends ListView implements AbsListView.OnScrollListener {

    private int firstPosition;//前一帧的位置

    private int durationFromTop;//当前可见的第二个view到top的距离

    private int duration; //移动距离

    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        if( ev.getAction() == MotionEvent.ACTION_DOWN) {//按下时初始化
            firstPosition = getFirstVisiblePosition();
            durationFromTop = getChildAt(1).getTop();
            duration = 0;
        }


        return super.onTouchEvent(ev);
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
    
        if(getChildAt(0) != null) {
            if(firstVisibleItem == firstPosition) { //情况一
                int nowDurationFromTop = getChildAt(1).getTop();
                duration = duration + durationFromTop - nowDurationFromTop;
                durationFromTop = nowDurationFromTop;
            } else if (firstVisibleItem > firstPosition) {//情况二
                duration = duration + durationFromTop - getChildAt(0).getTop();
                durationFromTop = getChildAt(1).getTop();
                firstPosition = firstVisibleItem;
            } else if (firstVisibleItem < firstPosition) {//情况三
                int position = 1+firstPosition-firstVisibleItem;
                if(position < 0 ) {
                    position = 0;
                } else if(position > visibleItemCount -1) {
                    position = visibleItemCount -1;
                }
                duration = duration + durationFromTop - getChildAt(position).getTop();
                durationFromTop = getChildAt(1).getTop();
                firstPosition = firstVisibleItem;
            }       
    }
}


需要注意的是,在listview高速滑动的情况下,会出现前后两帧的firstVisible view 不是相邻的位置,这种情况下,上面2,3种情况的距离就不好计算了。最后计算的情况会小于实际的滑动距离,误差是跳过的view高度之和。

0 0