本文来自http://blog.csdn.net/chenshaoyang0011 转载请申明文章出处!
文中如有纰漏之处,望不吝指教~~~欢迎讨论,共同学习~~~
Launcher桌面的一大功能就是支持左右滑动,这样的功能在现在的应用中使用非常广泛,并且有很多实现的方式,可以通过使用Fragment来实现也可以通过自定义的控件来实现。
Launcher采用了后者,这一功能的实现在Workspace来完成。首先来看一下Workspace的继承关系:
从图中可以看出Workspace是PagedView的子类,而实际上滑动功能的实现是在PagedView中实现的。在Launcher中,Workspace中有五个CellLayout,分别代表五个分屏。
当左右拖动CellLayout时,就能实现滑动的效果。但实际上CellLayout中还有其他的子View,PagedView是如何避免了来自子View的干扰的呢?这里就需要讨论另一个问题,Android对touch事件的拦截制度。而拦截发生在ViewGroup的onInterceptTouchEvent()和onTouchEvent()以及View的onTouchEvent中。当发生touch事件时,系统会产生一个MotionEvent并且沿着View Tree开始传递。首先获取MotionEvent是View Tree的根节点,根节点通常是一个ViewGroup,ViewGroup将在onInterceptTouchEvent()中获取MotionEvent并决定是否继续向下传递。当在ViewGroup.onInterceptEvent()中返回true时,将截获MotionEvent,View Tree下面的View将无法获得MotionEvent,转而交给当前ViewGroup的onTouchEvent()方法。如果onTouchEvent中返回false,那么MotionEvent将沿着View Tree向上传给上一层。拦截的过程草图如下:
有了touch事件的拦截机制之后,View tree中的各个层之间的分工也就更加明确了。在Launcher的View tree中,从上到下的主要的节点有,DragLayer,Workspace,CellLayout。DragLayer层的主要任务是负责对图标和AppWidget进行拖拽,Workspace则主要负责左右滑动,CellLayout则用于容纳各种桌面的快捷方式。大概的分工如下:
那么现在就进入PagedView中去了解实现的过程吧。
滑动功能主要分两步:1、在onInterceptTouchEvent中进行拦截。2、在onTouchEvent中进行滑动。
1,onInterceptTouchEvent(MotionEvent en)
在这个方法中,决定了什么时候截获MotionEvent来实现滑动,避免了子View的其他事件的影响(如点击事件)。
代码的主要工作是根据MotionEvent和当前的状态,在各个状态中切换mTouchState。其中一共有四个状态值,TOUCH_STATE_REST、TOUCH_STATE_SCROLLING、TOUCH_STATE_PREV_PAGE、TOUCH_STATE_NEXT_PAGE。状态之间的切换可以用如下的草图表示:
当mTouchState==TOUCH_STATE_REST时,不需要任何滑动操作,将MotionEvent向子View传递。这里,分析一种最简单的情况:初始桌面静止,手指按下,然后开始左右滑动。通过这种简单情况的分析,来帮助理解onInterceptTouceEvent的作用。开始桌面静止,则mTouchState==TOUCH_STATE_REST,触发switch分支中MotionEvent.ACTION_DOWN的代码。记录按下点的坐标,设置mAllowLongPress=true。由于mTouchState=TOUCH_STATE_REST,所以动作被传向了子View。接下来,在长按事件被触发之前移动手指则会在代码中调用determineScrollingStart()来决定是否进入滑动状态。进入滑动状态之后mTouchState的值就变为TOUCH_STATE_SCROLLING,然后onTouchEvent中的操作就会被用,开始滑动。
总结一下onInterceptTouchEvent()的工作就是:切换PagedView的状态,如果处于滑动状态就拦截。
2,onTouchEvent(MotionEvent en)
在这个方法中,执行各种关于滑动的工作的计算,界面的刷新等工作。
在onTouchEvent中,对接受到的不同的事件进行了分类的处理,大致可以将功能分类为:1、当接受到ACTION_DOWN时,若滑动正在进行,则停止。
2、当接受到ACTION_MOVE时,根据当前的状态调用scrollBy进行滑动或则调用determineScrollingStart准备开始滑动。
3、当接受到ACTION_UP时,根据当前所滑动的位移和速度,判断松手后进入到哪一个分屏。
到这里,Workspace滑动过程的基本流程就介绍完毕了。