《Android 自己动手写ListView学习其原理 1 显示第一屏Item》

《Android 自己动手写ListView学习其原理 2 上下滚动》

《Android 自己动手写ListView学习其原理 3 ItemClick,ItemLongClick,View复用》


之前已经写了《Android 自己动手写ListView学习其原理 1 显示第一屏Item》可以看到显示了一屏幕的Item但是并不能滚动,当前添加滚动功能。

ListView滚动如何实现呢?滚动操作时触摸视图,在视图上滑动之后ListView才会跟随手指滚动,这就很明确必须覆写onTouchEvent方法进行接收Touch事件并进行相应处理。



一、有图有真相

Android 自己动手写ListView学习其原理 2 上下滚动_第1张图片


二、覆写onTouchEvent

在按下的时候进行一些参数的初始化,移动的时候有多种状态,其状态值由mTouchMode变量记录,当前定义三种状态

    // 初始模式,用户还未接触ListView    private static final int TOUCH_MODE_REST = -1;    // 触摸Down事件模式    private static final int TOUCH_MODE_DOWN = 0;    // 滚动模式    private static final int TOUCH_MODE_SCROLL = 1;

onTouchEvent具体代码如下

@Overridepublic boolean onTouchEvent(MotionEvent event) {if (getChildCount() == 0) {return false;}final int y = (int) event.getY();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:startTouch(event);break;case MotionEvent.ACTION_MOVE:if (mTouchMode == TOUCH_MODE_DOWN) {startScrollIfNeeded(y);} else if (mTouchMode == TOUCH_MODE_SCROLL) {scrollList(y);}break;case MotionEvent.ACTION_UP:break;default:endTouch();break;}return true;}


滚动的关键就在scrollList(y), 而startScrollIfNeeded(y);只是判断当前是否足够滚动的条件,也就是是否滚动超过一定距离。

/** * 控制ListView进行滚动 *  * @param y 当前触摸点Y轴的值 */private void scrollList(int y) { // scrollIfNeeded// 当前手指坐在位置与刚触摸到屏幕之间的距离// 也就是当前手指在屏幕上Y轴总移动位置int scrolledDistance = y - mTouchStartY;// 改变当前记录的ListView顶部位置mListTop = mListTopStart + scrolledDistance;// 关键,要想使相面的计算生效必须重新请求布局// 会触发当前onLayout方法,指定Item位置与绘制先关还是在onLayout中requestLayout();}

上面代码已经写了充分的注释,这里就不再过多的解释了。


三、填充整个ListView

前一篇博文只是填充了一屏幕Item因为ListView不会滚动,所以并不需不要显示完整了,当前添加了滚动所以现在添加所有Item的支持。

先看下完整onLayout方法代码

@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {super.onLayout(changed, left, top, right, bottom);// 异常处理if (mAdapter == null) {return;}// 当前ListView没有任何子视图(Item),所以依次在从上向下填充子视图if (getChildCount() == 0) {mLastItemPosition = -1;// add and measurefillListDown(mListTop, 0);} else {final int offset = mListTop + mListTopOffset - getChildAt(0).getTop();// removefillList(offset);}// layout,添加测量完后,获取视图摆放位置positioinItems();// draw, 上面子视图都添加完了,重绘布局把子视图绘制出来吧invalidate();}


具体填充Item方法。

/** * ListView向上或者向下移动后需要向顶部或者底部添加视图 *  * @param offset */private void fillList(final int offset) {// 最后一个item的下边界值就是当前ListView的下边界值final int bottomEdge = getChildAt(getChildCount() - 1).getBottom();fillListDown(bottomEdge, offset);// 第一个Item的上边界值就是ListVie的上边界值final int topEdge = getChildAt(0).getTop();fillListUp(topEdge, offset);}/** * 与fillListDown相反方向添加 *  * @param topEdge 当前第一个子视图顶部边界值 * @param offset 显示区域偏移量 */private void fillListUp(int topEdge, int offset) {while (topEdge + offset > 0 && mFirstItemPosition > 0) {// 现在添加的视图时当前子视图后面,所以位置+1mLastItemPosition--;View newTopChild = mAdapter.getView(mFirstItemPosition, null, this);addAndMeasureChild(newTopChild, LAYOUT_MODE_ABOVE);int childHeight = newTopChild.getMeasuredHeight();topEdge -= childHeight;// 在顶部添加视图后,更新顶部偏移mListTopOffset -= childHeight;}}


四、源码下载


转载请注明出处:http://blog.csdn.net/love_world_/article/details/8743770




更多相关文章

  1. Android入门教程四十二之GridView(网格视图)的基本使用
  2. 视图模式:Android ViewPager & WP Pivot
  3. android TabWidget 位置
  4. Android 教你如何通过 LocationManager 获取得到当前位置坐标
  5. android视图继承关系
  6. Android 应用安装位置
  7. Android使用百度地图SDK获得当前设备位置所在的省、市(系列1)
  8. 第3.2.1节 android基本视图

随机推荐

  1. android “Debug certificate expired”&
  2. Android学习笔记(3):Android项目结构分析
  3. Android(安卓)图片压缩实现过程代码
  4. android拨号器...
  5. Android的SDK与源代码
  6. android UI进阶之弹窗的使用(2)--实现通讯
  7. Android(安卓)String类型转换为float、do
  8. Android网格布局的简单使用
  9. Android的framework层音量控制原理分析--
  10. Android常见小问题汇总