在Android中,若是出现须要展现的内容超过屏幕的大小,一般咱们会使用ScrollView和ListView来解决。本文将介绍这两种方法的原理。android
咱们先看看mScrollX/mScrollY在代码中的注释:canvas
mScrollX/mScrollY相对这个View的内容(文字,图片,子View)垂直/水平的像素偏移。以下图:缓存
在设置mScrollX / mScrollY后,就能够滚动到指定的“内容",而mScrollX/mScrollY 就是将内容原点(0,0)进行偏移的数值。函数
而这种内容大小以及偏移是如何发生的?在ViewGroup中,存在一个API drawChild(),这个函数主要完成对子View的空间大小的限制以及偏移,见以下的描述:rest
protected boolean drawChild(Canvas canvas, View child, long drawingTime) { boolean more = false; //获取子View的空间大小 final int cl = child.mLeft; final int ct = child.mTop; final int cr = child.mRight; final int cb = child.mBottom; //通知子View进行判断是否完成滚动,这里就是经过Scroller代码实现滚动的关键点 child.computeScroll(); //获取最新的偏移量 final int sx = child.mScrollX; final int sy = child.mScrollY; //建立一个还原点 final int restoreTo = canvas.save(); //偏移,经过这个API,实现了scroll对内容偏移, 先把内容的原点进行偏移到负数区域 canvas.translate(cl - sx, ct - sy); //剪切,由于以前有一个translate操做,全部剪切出来的空间就是父View给定的可见区域 //因此若是子View填充Canvas的内容超出给定的空间,也不会显示出来 canvas.clipRect(sx, sy, sx + (cr - cl), sy + (cb - ct)); //让子View进行绘图,注意子View不用处理Scroll属性,既能够实现内容偏移 child.draw(canvas); //还原 canvas.restoreToCount(restoreTo); return more; }
经过设置canvas的可见区域以及偏移平移坐标原点(0,0),就能够完成在固定大小内经过滚动显示被覆盖的部分。code
ListView和ScrollView有很大的区别:ListView仅仅须要几个View既能够实现滚动效果,而ScrollView须要所有的View。咱们来看一下ListView缓存机制:图片
因此ListView的滚动效果是经过替换ViewGroup上的子View来实现的。ip
在android中,为了实现滚动效果,一般有两种方式:原理
而ScrollView和ListView就是这两种实现的表明了。cli