Launcher 中的拖動都是交個DragLayer 來實現的,DragLayer中有2個重要的接口 DragSource 和 DropTarget。
DragSource 爲拖動對象的來源地,原始的Launcher中主要是指workspace,(還有文件夾也是Dragsource),
DropTarge 就是可以放置拖動對象的容器,WorkSpace,DeleteZone,UserFloder 都是DropTarget。
明確DragSource,DropTarget 這兩個概念後,就比較容易理解拖動的原理了:
拖動的原理: 把拖動對象(顯示爲dragView,攜帶信息draginfo) ,從原來的對象容器(dragSource)中刪除,然後 放入新的容器 (dropTarget)中。看上去很簡單哈。那麼代碼中具體是如何實現的呢? 我簡單描敘下:
在長按屏幕中的item後,在Launcher中啓動進入拖動模式,touch的move事件傳入 DragLayer 中,然後傳入 DragController 中,
在啓動函數 startDrag ( ) 中保存DragSource 和 Draginfo,然後在處理touch_move 事件的時候,處理拖動,在touch_up 事件中調用drop() 來放置拖動到View。
private boolean drop(float x, float y) {
final int[] coordinates = mCoordinatesTemp;
DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);//找到目標容器
if (dropTarget != null) {
dropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1],
(int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);// 這一步理解相對複雜點: 可以理解爲把當前移動的對象從 目標容器 上空移除,爲放置到容器內做準備。
if (dropTarget.acceptDrop(mDragSource, coordinates[0], coordinates[1],
(int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo)) {//判斷目標容器是否能可以放置當前的對象
dropTarget.onDrop(mDragSource, coordinates[0], coordinates[1],
(int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo);//目標容器添加當前拖動的對象
mDragSource.onDropCompleted((View) dropTarget, true);//來源容器調用完成拖動的處理
return true;
} else {
mDragSource.onDropCompleted((View) dropTarget, false);
return true;
}
}
return false;
}
具體到Workspace 中如何實現 OnDrop 和 onDropCompleted 就請查看源碼吧。