http://blog.csdn.net/stonecao/article/details/6561631
Luancher有一个相对比较复杂的功能就是拖放功能,要深入了解launcher,深入理解拖放功能是有必要的,这篇blog,我将对launcher的拖放功能做深入的了解
1.首先直观感受什么时候开始拖放?我们长按桌面一个应用图标或者控件的时候拖放就开始了,包括在all app view中长按应用图标,下面就是我截取的拖放开始的代码调用堆栈
at com.android.launcher2.DragController.startDrag(DragController.java:170)
at com.android.launcher2.Workspace.startDrag(Workspace.java:1068)
at com.android.launcher2.Launcher.onLongClick(Launcher.java:1683)
at android.view.View.performLongClick(View.java:2427)
at android.widget.TextView.performLongClick(TextView.java:7286)
at android.view.View$CheckForLongPress.run(View.java:8792)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:123)
桌面应用图标由Launcher.onLongClick负责监听处理,插入断点debug进入onLongclick函数
if (!(v instanceof CellLayout)) {
v = (View) v.getParent();
}
//获取桌面CellLayout上一个被拖动的对象
CellLayout.CellInfo cellInfo = (CellLayout.CellInfo) v.getTag();
...
if (mWorkspace.allowLongPress()) {
if (cellInfo.cell == null) {
...
} else {
if (!(cellInfo.cell instanceof Folder)) {
...
//调用Workspace.startDrag处理拖动
mWorkspace.startDrag(cellInfo);
}
}
}
我上面只写出关键代码,首先是获取被拖动的对象v.getTag(),Tag什么时候被设置进去的了
public boolean onInterceptTouchEvent(MotionEvent ev) {
...
if (action == MotionEvent.ACTION_DOWN) {
...
boolean found = false;
for (int i = count - 1; i >= 0; i--) {
final View child = getChildAt(i);
if ((child.getVisibility()) == VISIBLE || child.getAnimation() != null) {
child.getHitRect(frame);
//判断区域是否在这个子控件的区间,如果有把child信息赋给mCellInfo
if (frame.contains(x, y)) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
cellInfo.cell = child;
cellInfo.cellX = lp.cellX;
cellInfo.cellY = lp.cellY;
cellInfo.spanX = lp.cellHSpan;
cellInfo.spanY = lp.cellVSpan;
cellInfo.valid = true;
found = true;
mDirtyTag = false;
break;
}
}
}
mLastDownOnOccupiedCell = found;
if (!found) {
...
//没有child view 说明没有点击桌面图标项
cellInfo.cell = null;
}
setTag(cellInfo);
}
看了上面代码知道,当开始点击桌面时,celllayout就会根据点击区域去查找在该区域是否有child存在,若有把它设置为tag.cell,没有,tag.cell设置为null,后面在开始拖放时launcher.onlongclick中对tag进行处理,
这个理顺了,再深入到workspace.startDrag函数,workspace.startDrag调用DragController.startDrag去处理拖放
mDragController.startDrag(child, this, child.getTag(), DragController.DRAG_ACTION_MOVE);
再分析一下上面调用的几个参数
child = tag.cell
this = workspace
child.getTag()是什么呢?在什么时候被设置?