Android4.0 Launcher拖拽原理分析
在Android4.0源码自带的Launcher中,拖拽是由DragController进行控制的。
1) 先来看看类之间的继承关系
2)再来看看Launcher拖拽流程的时序图
1、基本流程:
- 相应的View在检测到用户操作后进行判断,若可以触发拖拽,则设置自身的相应状态,然后将待拖拽对象的Bitmap对象、当前位置、拖拽源、待拖拽对象等信息传给DragController的startDrag方法启动拖拽。
- 接下来,DragLayer的onInterceptTouchEvent拦截触屏事件,将其转到DragController的onTouchEvent方法。
- 在DragController的onTouchEvent中调用DragController的handleMoveEvent进行对象的移动,并通知相应拖拽目的对象状态的改变。
- 最后在DragController的onTouchEvent中检测到抬起事件时调用drop方法释放待拖拽对象,调用endDrag方法结束拖拽。
2、触发拖拽
在Launcher中,拖拽有两种方式触发:
- 在Workspace上进行拖拽;
- 从AppsCustomizePagedView中选择一个应用或Widget放置到Workspace上。
2.1 在Workspace上进行拖拽
1) 长按某个图标或Widget
在这种情况下,会调用Launcher的onLongClick方法,进而对于非文件夹调用Workspace的startDrag方法来隐藏相应视图并绘制图标边界(在Workspace上显示的用于标识当前拖拽图标所处位置的蓝色边界图形),最终转到Workspace.beginDragShared方法。

2) 在打开的文件夹中长按某个图标
在Launcher中,对于文件夹中元素的长按,是在Folder的onLongClick里处理的,故长按某个图标或Widget中,对于文件夹,则直接返回。
若允许拖拽,则调用Workspace的beginDragShared进行处理。

3) Workspace的beginDragShared方法
从上文中可以发现,只要是在Workspace上启动物体的拖拽,最终都会走到Workspace.beginDragShared方法里。在这个方法中,首先会通过createDragBitmap绘制用于拖拽的图形(包括在原图外层绘制一圈红色边界),然后计算位置与边界,并将其传给DragController管理。

2.2 从AppsCustomizePagedView中选择一个应用或Widget放置到Workspace上
AppsCustomizePagedView继承自PagedViewWithDraggableItems,即我们平时所说的应用程序抽屉。当长按应用图标或widget时,AppsCustomizePagedView会隐藏,显示Workspace的缩小状态,即SPRING_LOADED。
在源码中,该状态转换有三个入口,均在PagedViewWithDraggableItems中给出,即onInterceptTouchEvent、onTouchEvent与onLongClick。最终都转到AppsCustomizePagedView的beginDragging方法。但笔者试了多次,发现只有onLongClick被调用。

1) AppsCustomizePagedView的beginDragging
beginDragging类似一个代理方法,首先进行Launcher状态的转换,然后会根据被拖拽物的不同,调用不同的拖拽方法。

2) 应用程序的拖拽beginDraggingApplication
对于应用程序来说,从抽屉拖拽到桌面,界面的隐藏在beginDragging中都已经处理好了,AppsCustomizePagedView不需要保存任何有关被拖拽应用的信息(就算取消拖拽,也只需要重新显示AppsCustomizePagedView就行了,不像Folder那样还需要恢复快捷方式)。因此,只需要通知Workspace绘制图标边界,然后启动拖拽即可。

3) Widget/快捷方式的拖拽beginDraggingWidget
对于Widget列表中的元素,由于有可能为快捷方式,因此还需要进行判断。对不同类型的拖拽物,用不同的方式绘制图形及图标边界。

3、DragController拖拽控制流程
3.1 startDrag()开始拖拽
从上文可以发现,无论是以何种方式进入拖拽,最终都是调用DragController的startDrag方法进行处理。
在DragController中,startDrag是个多态方法,但最终,都走到了以下这个实现中。
startDrag的逻辑比较清晰,主要是通知相应的监听器拖拽开始,然后创建拖拽对象及其视图,将其移动到当前触摸到位置。

3.2 onInterceptTouchEvent()
DragLayer继承自ViewGroup,其onInterceptTouchEvent方法若返回true,说明需要拦截触屏事件,则后续的一系列事件将传递给自身的onTouchEvent方法,而不再向其子控件传递。
DragController的onInterceptTouchEvent由DragLayer的onInterceptTouchEvent调用,用于拦截触屏事件的处理。当用户点击屏幕时,触发ACTION_DOWN事件,记录当前触摸位置。当抬起时,触发ACTION_UP事件,结束拖拽。若抬起时处于拖拽中,在当前位置释放被拖拽物(在笔者测试过程中未检测到其调用)。最后,返回是否处于拖拽状态。
因此,若此时处于拖拽中,后续的触屏事件将只传递到DragLayer的onTouchEvent。
onTouchEvent()
onTouchEvent由于处理触屏事件,若返回true,则表示消费掉该事件,事件不再向父控件的onTouchEvent传递。
DragController的onTouchEvent由DragLayer的onTouchEvent调用,用于处理被拖拽物的移动。
当startDrag执行完毕,DragController设置拖拽状态为true,这样,触屏事件将最终转到onTouchEvent中,在此处调用handleMoveEvent进行物体的移动。其基本流程如下。

3.3 handleMoveEvent()进行移动
handleMoveEvent是拖拽的主要方法,当用户触发拖拽后,DragController将通过该方法移动被拖拽物视图,并通知各个释放目的对象相应状态的改变。若进入滑屏区域且允许滑屏,执行相应的滑屏操作。如下图所示。

3.4 drop()释放被拖拽物到当前位置
当用户将被拖拽物移动到相应位置后,可以将手指从屏幕上移开。此时,将在onInterceptTouchEvent(未试出)与onTouchEvent中调用drop方法释放被拖拽物。
其主要功能,就是查找拖拽目的对象(DropTarget),若找到且接受释放,通知该对象被拖拽物的放入。最后,通知拖拽源(被拖拽物最初所在的容器)拖拽结果。

findDropTarget()查找当前位置对应的拖拽目标对象
在handleMoveEvent与drop中,均使用了findDropTarget来查找当前位置对应的拖拽目的对象,其基本原理就是遍历所有已注册的拖拽目的对象,若其支持放入且当前位置位于该对象的触发区域内,则匹配成功返回该对象。

3.5 DragController拖拽控制流程总结
方法流程:(Launcher.onLongClick()-Workspace.beginDragShared()/AppsCustomizePagedView.beginDragging() -> )startDrag() -> onInterceptTouchEvent()/onTouchEvent() -> handleMoveEvent() -> drop()
总的来说,DragController拖拽控制就是(在进入拖拽之前的步骤见2触发拖拽):
- 进入拖拽:使用startDrag()进入拖拽状态;
- 响应触屏:使用onInterceptTouchEvent()与onTouchEvent()响应用户的触屏动作;
- 处理拖拽:使用handleMoveEvent()处理被拖拽物的移动;
- 释放拖拽:使用drop()将被拖拽物释放到相应位置。
注:Android 6.0后AppsCustomizePagedView更名为WidgetContainerView,功能系一脉相承
http://johnsonxu.iteye.com/blog/1933655
http://blog.csdn.net/wdaming1986/article/details/7671318
Android4.0 Launcher拖拽原理分析的更多相关文章
- Android Launcher拖拽事件详解【android4.0--Launcher系列二】
AndroidICS4.0版本的launcher拖 拽的流程,基本和2.3的相似.就是比2.3写的封装的接口多了一些,比如删除类的写法就多了个类.等等.4.0的改变有一些,但是不是特别大.这个月一 直 ...
- js拖拽原理及简单实现(渣渣自学)
第一步 首先简单分析下需求吧,我们就是想实现鼠标拖拽带颜色的方块时,让方块停留在鼠标松开的位置,需要计算的就是拖拽前的坐标和拖拽后的坐标,鼠标移动后相对于原位置的偏移量=目标元素的偏移量,根据这个等式 ...
- js拖拽原理和碰撞原理
拖拽的原理onmousedown 选择元素onmousemove 移动元素onmouseup 释放元素 1:如果拖拽的时候有文字:被选中,会产生问题原因:当鼠标按下的时如果页面中有文字或者图片被选中的 ...
- JS拖拽原理
实现拖拽效果主要跟鼠标的三个事件有关: onmousedown : 选择要拖拽的元素 onmousemove : 移动元素 onmouseup : 释放元素 三个事件的关系: obj.onmoused ...
- javascript拖拽原理与简单实现方法[demo]
美国人有一句常用的俗语—“Re-inventing the Wheel”,从字面上来解释就是“重新发明轮子”.可是轮子早已问世,再要去发明岂非劳而无功? 产品经理发下需求,实施者再到网上搜索代码,也许 ...
- JS鼠标的拖拽原理
拖拽功能主要是用在让用户做一些自定义的动作,比如拖动排序,弹出框拖动移动等等,效果还是蛮不错的.下面讲解一下拖拽的原理,希望可以帮助到有需要的朋友! 一.拖拽的流程动作①鼠标按下②鼠标移动③鼠标松开 ...
- Angular 2.0 文本拖拽
基于Angular7.1和TypeScript实现 Html代码 <div style="padding-left: 0px;"> <div id='conten ...
- Jquery拖拽原理
/* onmousedown : 选择元素 onmousemove : 移动元素 onmouseup : 释放元素 */ 查看Demo:拖拽图片 function drag(obj) { obj.on ...
- Android4.0 Launcher 源码分析2——Launcher内容加载绑定详细过程
Launcher在应用启动的时候,需要加载AppWidget,shortcut等内容项,通过调用LauncherModel.startLoader(),开始加载的工作.launcherModel中加载 ...
随机推荐
- JVM,Java虚拟机基础知识新手入门教程(超级通熟易懂)
作者:请叫我红领巾,转载请注明出处http://www.cnblogs.com/xxzhuang/p/7453746.html,简书地址:http://www.jianshu.com/p/b963b3 ...
- 理解Defer、Panic和Recover
刚开始的时候理解如何使用Defer和Recover有一点怪异,尤其是使用了try/catch块的时候.有一种模式可以在Go中实现和try/catch语句块一样的效果.不过之前你需要先领会Defer.P ...
- spring boot搭建Hello Word
一.安装与配置jdk 二.安装与配置maven 安装好maven,必须配置环境变量 通过cmd命令查询maven是否安装成功,以下是安装成功的界面 修改setting.xml的配置,制定本地仓库的路径 ...
- [Zend Mail]发送中文名附件出现乱码解决方案
Zend Framework 1.0.* “=?UTF-8?B?”.base64_encode($title).“?=” 发送中文名附件,结果如图: 英文名附件,结果截图: 解决办法就是将中文文件名拼 ...
- mdadm详细使用手册
1. 文档信息 当前版本 1.2 创建人 朱荣泽 创建时间 2011.01.07 修改历史 版本号 时间 内容 1.0 2011.01.07 创建<mdadm详细使用手册>1.0文档 1. ...
- test命令详解
test命令格式: test condition 通常,在if-then-else语句中,用[]代替,即[ condition ].注意:方括号两边都要用空格. 1.数值比较 ========== ...
- Log4Net从Mvc转到.Net Core
原项目用的Log4Net,不过版本比较旧,在Core里新版也进行了支持,本文用的是现在最新版本2.0.8 1.LogHelper帮助类放另一个类库中 Log/LogHelper.cs 2.单独建的配置 ...
- SQL导入的方法,网上看到的
-------这是一个新表,准备用来导入的表 CREATE TABLE CSVTable( Name NVARCHAR(MAX), Email NVARCHAR(MAX), Area NVARCHAR ...
- AtomicBoolean
它的两种用法: 1.保证某段语句只执行一次. 首先我们要知道compareAndSet的作用,判断对象当时内部值是否为第一个参数,如果是则更新为第二个参数,且返回ture,否则返回false.那么默认 ...
- Hash Table-720. Longest Word in Dictionary
Given a list of strings words representing an English Dictionary, find the longest word in words tha ...