android滑动实现原理,Android ScrollView 滚动机制

Android ScrollView 滚动机制

我们都知道通过View#scrollTo(x,y)既可以实现将View滚动的效果,如果再添加Scroller类,就可以实现滚到效果。但是,这背后是如何实现的呢?这个问题涉及到View的绘图机制。我们先看看View的绘图的基本流程

61698269_1.gif

(图片来自于网上比较常见的view绘图流程图)

关于三个阶段的简单描述:

1. measure:预估计ViewTree的各个View的占用空间。

2. layout :确定ViewTree中各个View所处的空间位置,包括width,height,left,top,right,bottom

3. draw:  使用RootViewImpl中的一个surface.lockCanvas(dirty)对象作为画布,然ViewTree上所有的View都在这个Canvas上进行画图,

值得注意的是,Canvas通过getHeight() 和 getWidth()就是整个屏幕的真实大小。包括了通知栏(虽然在打印出来的ViewTree看不到,但是通过top属性,留下了一点空间给通知栏),标题栏,Content,底部虚拟按键等。

我们先看看mScrollX/mScrollY在代码中的注释:

61698269_2.png

mScrollX/mScrollY相对这个View的内容(文字,图片,子View)垂直/水平的像素偏移。如下图:

61698269_3.png

在设置mScrollX / mScrollY后,就可以滚动到指定的“内容",而mScrollX/mScrollY就是相对于“内容”的偏移量,内容原点为(0,0)。

而这种内容大小以及偏移是如何发生的?在ViewGroup中,存在一个API drawChild(),这个函数主要完成对子View的空间大小的限制以及偏移,见如下的描述

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25protected 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;

}

值得注意的是,ListView不是采用这种机制实现的,而是采用替换ChildView来实现滑动效果的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值