创建一个拖动的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 = spanX;
lp.cellVSpan = spanY;
}
if
(spanX <
0
&& spanY <
0
) {
lp.isLockedToGrid =
false
;
}
int
childId = LauncherModel.getCellLayoutChildId(container, screen, x, y, spanX, spanY);
boolean
markCellsAsOccupied = !(child
instanceof
Folder);
if
(!layout.addViewToCellLayout(child, insert ?
0
: -
1
, childId, lp, markCellsAsOccupied)) {
Log.w(TAG,
"Failed to add to item at ("
+ lp.cellX +
","
+ lp.cellY +
") to CellLayout"
);
}
if
(!(child
instanceof
Folder)) {
child.setHapticFeedbackEnabled(
false
);
child.setOnLongClickListener(mLongClickListener);
}
if
(child
instanceof
DropTarget) {
mDragController.addDropTarget((DropTarget) child);
}
}</pre><br>
这里做了一些计算,拖动的是什么,放在哪里等等吧,然后就layout.addViewToCellLayout(child, insert ?
0
: -
1
, childId, lp, markCellsAsOccupied)这里的layout是CellLayout所以layout.addViewToCellLayout也就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
public
boolean
addViewToCellLayout(
View child,
int
index,
int
childId, LayoutParams params,
boolean
markCells) {
final
LayoutParams lp = params;
if
(lp.cellX >=
0
&& lp.cellX <= mCountX -
1
&& lp.cellY >=
0
&& lp.cellY <= mCountY -
1
) {
if
(lp.cellHSpan <
0
) lp.cellHSpan = mCountX;
if
(lp.cellVSpan <
0
) lp.cellVSpan = mCountY;
child.setId(childId);
mChildren.addView(child, index, lp);
if
(markCells) markCellsAsOccupiedForView(child);
return
true
;
}
return
false
;
}</pre><br>
也就是mChildren.addView(child, index, lp)了,这里的mChildren也就是CellLayoutChildren,CellLayoutChildren我们前面说过了,就不再说了,至此一个移动过程结束。现在我们回过头来看看如果是从主菜单拖到workspace待机是怎么一个过程,这个过程主要是从主菜单到workspace的转换过程,我们还是从长按事件开始,从主菜单长按事件应该在AppsCustomizePagedView里面,但是这里没有,我们去它的父类PagedViewWithDraggableItems中寻找,也就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
@Override
public
boolean
onLongClick(View v) {
if
(!v.isInTouchMode())
return
false
;
if
(mNextPage != INVALID_PAGE)
return
false
;
if
(!mLauncher.isAllAppsCustomizeOpen() ||
mLauncher.getWorkspace().isSwitchingState())
return
false
;
return
beginDragging(v);
}</pre><br>
也就是beginDragging,beginDragging在其子类AppsCustomizePagedView中重写了,也就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
@Override
protected
boolean
beginDragging(View v) {
mLauncher.dismissAllAppsCling(
null
);
if
(!
super
.beginDragging(v))
return
false
;
mLauncher.enterSpringLoadedDragMode();
if
(v
instanceof
PagedViewIcon) {
beginDraggingApplication(v);
}
else
if
(v
instanceof
PagedViewWidget) {
beginDraggingWidget(v);
}
return
true
;
}</pre><br>
mLauncher.enterSpringLoadedDragMode()是做什么的呢?就是隐藏主菜单,显示workspace待机,这样就从显示上切换到workspace了,但是实质还没切换到workspace,这个后面会讲到,然后就是区分开拖动的是PagedViewIcon(App图标),还是PagedViewWidget(widget图标)。这里我们只看App图标,也就是beginDraggingApplication(v)
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
private
void
beginDraggingApplication(View v) {
mLauncher.getWorkspace().onDragStartedWithItem(v);
mLauncher.getWorkspace().beginDragShared(v,
this
);
}</pre><br>
这里就是实质上切换到workspace了,先看上面一句mLauncher.getWorkspace().onDragStartedWithItem(v)也就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
public
void
onDragStartedWithItem(View v) {
final
Canvas canvas =
new
Canvas();
final
int
bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
mDragOutline = createDragOutline(v, canvas, bitmapPadding);
}</pre><br>
这里同样创建了一个Bitmap为mDragOutline,和刚才我们讲解workspace拖动一样啦,就不再说了,然后看看下句mLauncher.getWorkspace().beginDragShared(v,
this
)也就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
public
void
beginDragShared(View child, DragSource source) {
Resources r = getResources();
final
int
bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
final
Bitmap b = createDragBitmap(child,
new
Canvas(), bitmapPadding);
final
int
bmpWidth = b.getWidth();
mLauncher.getDragLayer().getLocationInDragLayer(child, mTempXY);
final
int
dragLayerX = (
int
) mTempXY[
0
] + (child.getWidth() - bmpWidth) /
2
;
int
dragLayerY = mTempXY[
1
] - bitmapPadding /
2
;
Point dragVisualizeOffset =
null
;
Rect dragRect =
null
;
if
(child
instanceof
BubbleTextView || child
instanceof
PagedViewIcon) {
int
iconSize = r.getDimensionPixelSize(R.dimen.app_icon_size);
int
iconPaddingTop = r.getDimensionPixelSize(R.dimen.app_icon_padding_top);
int
top = child.getPaddingTop();
int
left = (bmpWidth - iconSize) /
2
;
int
right = left + iconSize;
int
bottom = top + iconSize;
dragLayerY += top;
dragVisualizeOffset =
new
Point(-bitmapPadding /
2
, iconPaddingTop - bitmapPadding /
2
);
dragRect =
new
Rect(left, top, right, bottom);
}
else
if
(child
instanceof
FolderIcon) {
int
previewSize = r.getDimensionPixelSize(R.dimen.folder_preview_size);
dragRect =
new
Rect(
0
,
0
, child.getWidth(), previewSize);
}
if
(child
instanceof
BubbleTextView) {
BubbleTextView icon = (BubbleTextView) child;
icon.clearPressedOrFocusedBackground();
}
mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect);
b.recycle();
}</pre><br>
又到了这里了,这个和刚才workspace拖动是一样的了,也不做解释了,然后就进入mDragController.startDrag再然后就是handleMoveEvent循环了,然后就是拖到适当位置MotionEvent.ACTION_UP消息了,然后就是drop,dropTarget.onDrop这些过程和workspace拖动过程都一样了,唯独到了Workspace的onDrop中不同,也就是我们前面提到的,当从主菜单托出图标是会走onDropExternal(touchXY, d.dragInfo,
dropTargetLayout,
false
, d)也就是
<p></p>
<p></p>
<pre
class
=
"brush:java;"
>
private
void
onDropExternal(
final
int
[] touchXY,
final
Object dragInfo,
final
CellLayout cellLayout,
boolean
insertAtFirst, DragObject d) {
final
Runnable exitSpringLoadedRunnable =
new
Runnable() {
@Override
public
void
run() {
mLauncher.exitSpringLoadedDragModeDelayed(
true
,
false
);
}
};
ItemInfo info = (ItemInfo) dragInfo;
int
spanX = info.spanX;
int
spanY = info.spanY;
if
(mDragInfo !=
null
) {
spanX = mDragInfo.spanX;
spanY = mDragInfo.spanY;
}
final
long
container = mLauncher.isHotseatLayout(cellLayout) ?
LauncherSettings.Favorites.CONTAINER_HOTSEAT :
LauncherSettings.Favorites.CONTAINER_DESKTOP;
final
int
screen = indexOfChild(cellLayout);
if
(!mLauncher.isHotseatLayout(cellLayout) && screen != mCurrentPage
&& mState != State.SPRING_LOADED) {
snapToPage(screen);
}
if
(info
instanceof
PendingAddItemInfo) {
final
PendingAddItemInfo pendingInfo = (PendingAddItemInfo) dragInfo;
boolean
findNearestVacantCell =
true
;
if
(pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
mTargetCell = findNearestArea((
int
) touchXY[
0
], (
int
) touchXY[
1
], spanX, spanY,
cellLayout, mTargetCell);
if
(willCreateUserFolder((ItemInfo) d.dragInfo, mDragTargetLayout, mTargetCell,
true
) || willAddToExistingUserFolder((ItemInfo) d.dragInfo,
mDragTargetLayout, mTargetCell)) {
findNearestVacantCell =
false
;
}
}
if
(findNearestVacantCell) {
mTargetCell = findNearestVacantArea(touchXY[
0
], touchXY[
1
], spanX, spanY,
null
,
cellLayout, mTargetCell);
}
Runnable onAnimationCompleteRunnable =
new
Runnable() {
@Override
public
void
run() {
switch
(pendingInfo.itemType) {
case
LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) pendingInfo,
container, screen, mTargetCell,
null
);
break
;
case
LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
mLauncher.processShortcutFromDrop(pendingInfo.componentName,
container, screen, mTargetCell,
null
);
break
;
default
:
throw
new
IllegalStateException(
"Unknown item type: "
+
pendingInfo.itemType);
}
cellLayout.onDragExit();
}
};
RectF r = estimateItemPosition(cellLayout, pendingInfo,
mTargetCell[
0
], mTargetCell[
1
], spanX, spanY);
int
loc[] =
new
int
[
2
];
loc[
0
] = (
int
) r.left;
loc[
1
] = (
int
) r.top;
setFinalTransitionTransform(cellLayout);
float
cellLayoutScale =
mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(cellLayout, loc);
resetTransitionTransform(cellLayout);
float
dragViewScale = Math.min(r.width() / d.dragView.getMeasuredWidth(),
r.height() / d.dragView.getMeasuredHeight());
loc[
0
] -= (d.dragView.getMeasuredWidth() - cellLayoutScale * r.width()) /
2
;
loc[
1
] -= (d.dragView.getMeasuredHeight() - cellLayoutScale * r.height()) /
2
;
mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, loc,
dragViewScale * cellLayoutScale, onAnimationCompleteRunnable);
}
else
{
View view =
null
;
switch
(info.itemType) {
case
LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case
LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
if
(info.container == NO_ID && info
instanceof
ApplicationInfo) {
info =
new
ShortcutInfo((ApplicationInfo) info);
}
view = mLauncher.createShortcut(R.layout.application, cellLayout,
(ShortcutInfo) info);
break
;
case
LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, cellLayout,
(FolderInfo) info, mIconCache);
break
;
default
:
throw
new
IllegalStateException(
"Unknown item type: "
+ info.itemType);
}
if
(touchXY !=
null
) {
mTargetCell = findNearestArea((
int
) touchXY[
0
], (
int
) touchXY[
1
], spanX, spanY,
cellLayout, mTargetCell);
d.postAnimationRunnable = exitSpringLoadedRunnable;
if
(createUserFolderIfNecessary(view, container, cellLayout, mTargetCell,
true
,
d.dragView, d.postAnimationRunnable)) {
return
;
}
if
(addToExistingFolderIfNecessary(view, cellLayout, mTargetCell, d,
true
)) {
return
;
}
}
if
(touchXY !=
null
) {
mTargetCell = findNearestVacantArea(touchXY[
0
], touchXY[
1
],
1
,
1
,
null
,
cellLayout, mTargetCell);
}
else
{
cellLayout.findCellForSpan(mTargetCell,
1
,
1
);
}
addInScreen(view, container, screen, mTargetCell[
0
], mTargetCell[
1
], info.spanX,
info.spanY, insertAtFirst);
cellLayout.onDropChild(view);
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
cellLayout.getChildrenLayout().measureChild(view);
LauncherModel.addOrMoveItemInDatabase(mLauncher, info, container, screen,
lp.cellX, lp.cellY);
if
(d.dragView !=
null
) {
setFinalTransitionTransform(cellLayout);
mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, view,
exitSpringLoadedRunnable);
resetTransitionTransform(cellLayout);
}
}
}</pre><br>
这里也分为两个部分一部分是PendingAddItemInfo,PendingAddItemInfo是Widget有关的,这里不再详解,而我们的应用图标又会走到
<p></p>
<p></p>
<pre
class
=
"brush:java;"
> addInScreen(view, container, screen, mTargetCell[
0
], mTargetCell[
1
], info.spanX,
info.spanY, insertAtFirst);</pre><br>
这里,addInScreen我们上面已经讲解过了,这里就不再赘述了。其它的内容不再讲解,有兴趣自己研究吧。至此我们的拖动过程就讲解完了。
<p></p>
<p> 这篇中我们讲解了Launcher图标的加载过程,点击图标进入应用的过程,拖动图标的过程,至于安装应用、卸载应用、更新应用、壁纸、widget等等其它Launcher内容,如果有需以后再讲解吧。</p>
<p> 还是那句话,给大师们茶余饭后取乐,给后来者抛砖引玉,不要在背后骂我就谢天谢地了。<br>
</p>
<p><br>
</p> </applicationinfo></n></pre></n>