创建一个拖动的Bitmap这个和刚才的mDragOutline不同,这个Bitmap透明度、大小等等有变化的。然后就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
> mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect);</pre><br>
也就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
public
void
startDrag(Bitmap b,
int
dragLayerX,
int
dragLayerY,
DragSource source, Object dragInfo,
int
dragAction, Point dragOffset, Rect dragRegion) {
if
(PROFILE_DRAWING_DURING_DRAG) {
android.os.Debug.startMethodTracing(
"Launcher"
);
}
if
(mInputMethodManager ==
null
) {
mInputMethodManager = (InputMethodManager)
mLauncher.getSystemService(Context.INPUT_METHOD_SERVICE);
}
mInputMethodManager.hideSoftInputFromWindow(mWindowToken,
0
);
for
(DragListener listener : mListeners) {
listener.onDragStart(source, dragInfo, dragAction);
}
final
int
registrationX = mMotionDownX - dragLayerX;
final
int
registrationY = mMotionDownY - dragLayerY;
final
int
dragRegionLeft = dragRegion ==
null
?
0
: dragRegion.left;
final
int
dragRegionTop = dragRegion ==
null
?
0
: dragRegion.top;
mDragging =
true
;
mDragObject =
new
DropTarget.DragObject();
mDragObject.dragComplete =
false
;
mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);
mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);
mDragObject.dragSource = source;
mDragObject.dragInfo = dragInfo;
mVibrator.vibrate(VIBRATE_DURATION);
final
DragView dragView = mDragObject.dragView =
new
DragView(mLauncher, b, registrationX,
registrationY,
0
,
0
, b.getWidth(), b.getHeight());
if
(dragOffset !=
null
) {
dragView.setDragVisualizeOffset(
new
Point(dragOffset));
}
if
(dragRegion !=
null
) {
dragView.setDragRegion(
new
Rect(dragRegion));
}
dragView.show(mMotionDownX, mMotionDownY);
handleMoveEvent(mMotionDownX, mMotionDownY);
}</pre><br>
创建一个DragView然后显示dragView.show,长按的时候会震动一下也就是在这里mVibrator.vibrate(VIBRATE_DURATION),最终handleMoveEvent(mMotionDownX, mMotionDownY)也就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
private
void
handleMoveEvent(
int
x,
int
y) {
mDragObject.dragView.move(x, y);
final
int
[] coordinates = mCoordinatesTemp;
DropTarget dropTarget = findDropTarget(x, y, coordinates);
mDragObject.x = coordinates[
0
];
mDragObject.y = coordinates[
1
];
if
(dropTarget !=
null
) {
DropTarget delegate = dropTarget.getDropTargetDelegate(mDragObject);
if
(delegate !=
null
) {
dropTarget = delegate;
}
if
(mLastDropTarget != dropTarget) {
if
(mLastDropTarget !=
null
) {
mLastDropTarget.onDragExit(mDragObject);
}
dropTarget.onDragEnter(mDragObject);
}
dropTarget.onDragOver(mDragObject);
}
else
{
if
(mLastDropTarget !=
null
) {
mLastDropTarget.onDragExit(mDragObject);
}
}
mLastDropTarget = dropTarget;
final
int
slop = ViewConfiguration.get(mLauncher).getScaledWindowTouchSlop();
mDistanceSinceScroll +=
Math.sqrt(Math.pow(mLastTouch[
0
] - x,
2
) + Math.pow(mLastTouch[
1
] - y,
2
));
mLastTouch[
0
] = x;
mLastTouch[
1
] = y;
if
(x < mScrollZone) {
if
(mScrollState == SCROLL_OUTSIDE_ZONE && mDistanceSinceScroll > slop) {
mScrollState = SCROLL_WAITING_IN_ZONE;
if
(mDragScroller.onEnterScrollArea(x, y, SCROLL_LEFT)) {
mScrollRunnable.setDirection(SCROLL_LEFT);
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
}
}
}
else
if
(x > mScrollView.getWidth() - mScrollZone) {
if
(mScrollState == SCROLL_OUTSIDE_ZONE && mDistanceSinceScroll > slop) {
mScrollState = SCROLL_WAITING_IN_ZONE;
if
(mDragScroller.onEnterScrollArea(x, y, SCROLL_RIGHT)) {
mScrollRunnable.setDirection(SCROLL_RIGHT);
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
}
}
}
else
{
if
(mScrollState == SCROLL_WAITING_IN_ZONE) {
mScrollState = SCROLL_OUTSIDE_ZONE;
mScrollRunnable.setDirection(SCROLL_RIGHT);
mHandler.removeCallbacks(mScrollRunnable);
mDragScroller.onExitScrollArea();
}
}
}</pre><br>
当开始拖动的时候也就开始分发ACTION_MOVE消息,也就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
public
boolean
onTouchEvent(MotionEvent ev) {
if
(!mDragging) {
return
false
;
}
final
int
action = ev.getAction();
final
int
[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
final
int
dragLayerX = dragLayerPos[
0
];
final
int
dragLayerY = dragLayerPos[
1
];
switch
(action) {
case
MotionEvent.ACTION_DOWN:
mMotionDownX = dragLayerX;
mMotionDownY = dragLayerY;
if
((dragLayerX < mScrollZone) || (dragLayerX > mScrollView.getWidth() - mScrollZone)) {
mScrollState = SCROLL_WAITING_IN_ZONE;
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
}
else
{
mScrollState = SCROLL_OUTSIDE_ZONE;
}
break
;
case
MotionEvent.ACTION_MOVE:
handleMoveEvent(dragLayerX, dragLayerY);
break
;
case
MotionEvent.ACTION_UP:
handleMoveEvent(dragLayerX, dragLayerY);
mHandler.removeCallbacks(mScrollRunnable);
if
(mDragging) {
drop(dragLayerX, dragLayerY);
}
endDrag();
break
;
case
MotionEvent.ACTION_CANCEL:
cancelDrag();
break
;
}
return
true
;
}</pre><br>
这里的MotionEvent.ACTION_MOVE消息,一直重复handleMoveEvent,当松手的时候就是MotionEvent.ACTION_UP了。我们还先回到handleMoveEvent看看
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>mDragObject.dragView.move(x, y);</pre><br>
这个就是拖动的过程了,也就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
void
move(
int
touchX,
int
touchY) {
DragLayer.LayoutParams lp = mLayoutParams;
lp.x = touchX - mRegistrationX + (
int
) mOffsetX;
lp.y = touchY - mRegistrationY + (
int
) mOffsetY;
mDragLayer.requestLayout();
}
</pre><br>
一直更改坐标,然后更新。然后还回到handleMoveEvent下面的内容是什么呢?大致解释一下不再深入解析,就是当drop也就是UP松手时做的一下事情,和当移动到边缘时切换到下一页,这些不再讲解。然后我们回到MotionEvent.ACTION_UP消息,也就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
> handleMoveEvent(dragLayerX, dragLayerY);
mHandler.removeCallbacks(mScrollRunnable);
if
(mDragging) {
drop(dragLayerX, dragLayerY);
}
endDrag();</pre><br>
handleMoveEvent我们刚才已经说过了,endDrag()时拖动结束释放资源,我们单看drop(dragLayerX, dragLayerY)也就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
private
void
drop(
float
x,
float
y) {
final
int
[] coordinates = mCoordinatesTemp;
final
DropTarget dropTarget = findDropTarget((
int
) x, (
int
) y, coordinates);
mDragObject.x = coordinates[
0
];
mDragObject.y = coordinates[
1
];
boolean
accepted =
false
;
if
(dropTarget !=
null
) {
mDragObject.dragComplete =
true
;
dropTarget.onDragExit(mDragObject);
if
(dropTarget.acceptDrop(mDragObject)) {
dropTarget.onDrop(mDragObject);
accepted =
true
;
}
}
mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject, accepted);
}</pre><br>
也就是dropTarget.onDrop(mDragObject),其它内容不做详解,都是放松手后做了一些处理,我们只看看dropTarget.onDrop(mDragObject),DropTarget是个接口,在Workspace中实现
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
public
void
onDrop(DragObject d) {
mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView,
mDragViewVisualCenter);
if
(mDragTargetLayout !=
null
) {
if
(mLauncher.isHotseatLayout(mDragTargetLayout)) {
mapPointFromSelfToSibling(mLauncher.getHotseat(), mDragViewVisualCenter);
}
else
{
mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter,
null
);
}
}
CellLayout dropTargetLayout = mDragTargetLayout;
int
snapScreen = -
1
;
if
(d.dragSource !=
this
) {
final
int
[] touchXY =
new
int
[] { (
int
) mDragViewVisualCenter[
0
],
(
int
) mDragViewVisualCenter[
1
] };
onDropExternal(touchXY, d.dragInfo, dropTargetLayout,
false
, d);
}
else
if
(mDragInfo !=
null
) {
final
View cell = mDragInfo.cell;
if
(dropTargetLayout !=
null
) {
boolean
hasMovedLayouts = (getParentCellLayoutForView(cell) != dropTargetLayout);
boolean
hasMovedIntoHotseat = mLauncher.isHotseatLayout(dropTargetLayout);
long
container = hasMovedIntoHotseat ?
LauncherSettings.Favorites.CONTAINER_HOTSEAT :
LauncherSettings.Favorites.CONTAINER_DESKTOP;
int
screen = (mTargetCell[
0
] <
0
) ?
mDragInfo.screen : indexOfChild(dropTargetLayout);
int
spanX = mDragInfo !=
null
? mDragInfo.spanX :
1
;
int
spanY = mDragInfo !=
null
? mDragInfo.spanY :
1
;
mTargetCell = findNearestArea((
int
) mDragViewVisualCenter[
0
], (
int
)
mDragViewVisualCenter[
1
], spanX, spanY, dropTargetLayout, mTargetCell);
if
(!mInScrollArea && createUserFolderIfNecessary(cell, container,
dropTargetLayout, mTargetCell,
false
, d.dragView,
null
)) {
return
;
}
if
(addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell, d,
false
)) {
return
;
}
mTargetCell = findNearestVacantArea((
int
) mDragViewVisualCenter[
0
],
(
int
) mDragViewVisualCenter[
1
], mDragInfo.spanX, mDragInfo.spanY, cell,
dropTargetLayout, mTargetCell);
if
(mCurrentPage != screen && !hasMovedIntoHotseat) {
snapScreen = screen;
snapToPage(screen);
}
if
(mTargetCell[
0
] >=
0
&& mTargetCell[
1
] >=
0
) {
if
(hasMovedLayouts) {
if
(getParentCellLayoutForView(cell) !=
null
){
getParentCellLayoutForView(cell).removeView(cell);
}
else
{
Log.d(TAG,
"this view not be added to CellLayout"
);
}
addInScreen(cell, container, screen, mTargetCell[
0
], mTargetCell[
1
],
mDragInfo.spanX, mDragInfo.spanY);
}
final
ItemInfo info = (ItemInfo) cell.getTag();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
dropTargetLayout.onMove(cell, mTargetCell[
0
], mTargetCell[
1
]);
lp.cellX = mTargetCell[
0
];
lp.cellY = mTargetCell[
1
];
cell.setId(LauncherModel.getCellLayoutChildId(container, mDragInfo.screen,
mTargetCell[
0
], mTargetCell[
1
], mDragInfo.spanX, mDragInfo.spanY));
if
(container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&
cell
instanceof
LauncherAppWidgetHostView) {
final
CellLayout cellLayout = dropTargetLayout;
final
LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;
AppWidgetProviderInfo pinfo = hostView.getAppWidgetInfo();
if
(pinfo !=
null
&& pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
final
Runnable resizeRunnable =
new
Runnable() {
public
void
run() {
DragLayer dragLayer = mLauncher.getDragLayer();
dragLayer.addResizeFrame(info, hostView, cellLayout);
}
};
post(
new
Runnable() {
public
void
run() {
if
(!isPageMoving()) {
resizeRunnable.run();
}
else
{
mDelayedResizeRunnable = resizeRunnable;
}
}
});
}
}
ItemInfo modelItem =
null
;
if
(info !=
null
) {
modelItem = LauncherModel.sItemsIdMap.get(info.id);
}
if
(modelItem ==
null
){
/**Bug141020 Bug146476 start.if the item has been deleted from db ,such as stk1 ,stk2,
* just return,if the item is Folder and there is no other Shorcut except stk1 ,stk2
* delete the Emputy Folder**/
if
(cell
instanceof
FolderIcon){
FolderIcon folder= (FolderIcon)cell;
ArrayList<view> folderItem = folder.mFolder.getItemsInReadingOrder();
if
(folderItem.size() ==
0
){
getParentCellLayoutForView(cell).removeView(cell);
}
}
return
;
}
LauncherModel.moveItemInDatabase(mLauncher, info, container, screen, lp.cellX,
lp.cellY);
}
}
final
CellLayout parent = (CellLayout) cell.getParent().getParent();
final
Runnable disableHardwareLayersRunnable =
new
Runnable() {
@Override
public
void
run() {
mAnimatingViewIntoPlace =
false
;
updateChildrenLayersEnabled();
}
};
mAnimatingViewIntoPlace =
true
;
if
(d.dragView.hasDrawn()) {
int
duration = snapScreen <
0
? -
1
: ADJACENT_SCREEN_DROP_DURATION;
setFinalScrollForPageChange(snapScreen);
mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell, duration,
disableHardwareLayersRunnable);
resetFinalScrollForPageChange(snapScreen);
}
else
{
cell.setVisibility(VISIBLE);
}
parent.onDropChild(cell);
}
}</view></pre><br>
这个函数比较大,就不一一解释了,大概说一下,分为三种情况,第一如果是从主菜单拖到workspace待机的走onDropExternal(touchXY, d.dragInfo, dropTargetLayout,
false
, d)这里,如果是在workspace拖动的,分两种情况,一种就是没有把该图标拖到另外一页,就更新刷新就完了,如果拖到了下一页就走
<p></p>
<p></p>
<pre
class
=
"brush:java;"
> addInScreen(cell, container, screen, mTargetCell[
0
], mTargetCell[
1
],
mDragInfo.spanX, mDragInfo.spanY);</pre><br>
addInScreen也就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
void
addInScreen(View child,
long
container,
int
screen,
int
x,
int
y,
int
spanX,
int
spanY,
boolean
insert) {
if
(container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
if
(screen <
0
|| screen >= getChildCount()) {
Log.e(TAG,
"The screen must be >= 0 and < "
+ getChildCount()
+
" (was "
+ screen +
"); skipping child"
);
return
;
}
}
final
CellLayout layout;
if
(container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
layout = mLauncher.getHotseat().getLayout();
child.setOnKeyListener(
null
);
if
(child
instanceof
FolderIcon) {
((FolderIcon) child).setTextVisible(
false
);
}
if
(screen <
0
) {
screen = mLauncher.getHotseat().getOrderInHotseat(x, y);
}
else
{
x = mLauncher.getHotseat().getCellXFromOrder(screen);
y = mLauncher.getHotseat().getCellYFromOrder(screen);
}
}
else
{
if
(child
instanceof
FolderIcon) {
((FolderIcon) child).setTextVisible(
true
);
}
layout = (CellLayout) getChildAt(screen);
child.setOnKeyListener(
new
IconKeyEventListener());
}
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
if
(lp ==
null
) {
lp =
new
CellLayout.LayoutParams(x, y, spanX, spanY);
}
else
{
lp.cellX = x;
lp.cellY = y;
lp.cellHSpan = sp