Launcher3/src/com/android/launcher3/Workspace.java
Workspace
开始拖拽时调用到startDrag()方法
private int mAppStartDragScreenIndex;
private int mAppStartDragScreenAppCount;
public void startDrag(CellLayout.CellInfo cellInfo, DragOptions options) {
View child = cellInfo.cell;
mDragInfo = cellInfo;
child.setVisibility(INVISIBLE);
//开始拖拽时当前屏的索引号
mAppStartDragScreenIndex = cellInfo.screenId;
//开始拖拽时当前屏的APP数目
CellLayout cellLayout = mWorkspaceScreens.valueAt(mAppStartDragScreenIndex);
if(null != cellLayout.getShortcutsAndWidgets()){
mAppStartDragScreenAppCount = cellLayout.getShortcutsAndWidgets().getChildCount();
}
if (options.isAccessibleDrag) {
mDragController.addDragListener(
new AccessibleDragListenerAdapter(this, WorkspaceAccessibilityHelper::new) {
@Override
protected void enableAccessibleDrag(boolean enable) {
super.enableAccessibleDrag(enable);
setEnableForLayout(mLauncher.getHotseat(), enable);
}
});
}
beginDragShared(child, this, options);
}
拖拽到区域放下时触发onDrop()方法回调
if (dropTargetLayout != null && !d.cancelled) {}
如果不满足条件,APP拖拽时放下,图标会自动回到原来的位置,所以这里加上最后一屏条件判断
dropToScreenIndex,拖拽到屏幕的索引号
mAppStartDragScreenIndex ,开始拖拽时当前屏的索引号
mAppStartDragScreenAppCount ,开始拖拽时当前屏的APP数目
@Override
public void onDrop(final DragObject d, DragOptions options) {
mDragViewVisualCenter = d.getVisualCenter(mDragViewVisualCenter);
CellLayout dropTargetLayout = mDropToLayout;
// We want the point to be mapped to the dragTarget.
if (dropTargetLayout != null) {
mapPointFromDropLayout(dropTargetLayout, mDragViewVisualCenter);
}
boolean droppedOnOriginalCell = false;
boolean snappedToNewPage = false;
boolean resizeOnDrop = false;
Runnable onCompleteRunnable = null;
if (d.dragSource != this || mDragInfo == null) {
final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1] };
onDropExternal(touchXY, dropTargetLayout, d);
} else {
final View cell = mDragInfo.cell;
boolean droppedOnOriginalCellDuringTransition = false;
boolean isCanDrop = true;
int pageCanDropTotalCount = dropTargetLayout.getCountX()*dropTargetLayout.getCountY();
int dropToScreenIndex = getIdForScreen(dropTargetLayout);
//拖拽到空屏,也就是最后一屏的下一个空屏
if((dropToScreenIndex+1)>=mWorkspaceScreens.size()
//mCurAppStartDragScreenIndex开始拖拽时屏幕的索引号,这里指从最后一屏开始拖拽时
&& (mAppStartDragScreenIndex +1) == mWorkspaceScreens.size()-1 &&
mAppStartDragScreenAppCount < (pageCanDropTotalCount - 6)){
isCanDrop = false;
}
if (dropTargetLayout != null && !d.cancelled && isCanDrop) {
// Move internally
boolean hasMovedLayouts = (getParentCellLayoutForView(cell) != dropTargetLayout);
boolean hasMovedIntoHotseat = mLauncher.isHotseatLayout(dropTargetLayout);
int container = hasMovedIntoHotseat ?
LauncherSettings.Favorites.CONTAINER_HOTSEAT :
LauncherSettings.Favorites.CONTAINER_DESKTOP;
int screenId = (mTargetCell[0] < 0) ?
mDragInfo.screenId : getIdForScreen(dropTargetLayout);
int spanX = mDragInfo != null ? mDragInfo.spanX : 1;
int spanY = mDragInfo != null ? mDragInfo.spanY : 1;
// First we find the cell nearest to point at which the item is
// dropped, without any consideration to whether there is an item there.
mTargetCell = findNearestArea((int) mDragViewVisualCenter[0], (int)
mDragViewVisualCenter[1], spanX, spanY, dropTargetLayout, mTargetCell);
float distance = dropTargetLayout.getDistanceFromWorkspaceCellVisualCenter(
mDragViewVisualCenter[0], mDragViewVisualCenter[1], mTargetCell);
// If the item being dropped is a shortcut and the nearest drop
// cell also contains a shortcut, then create a folder with the two shortcuts.
if (createUserFolderIfNecessary(cell, container, dropTargetLayout, mTargetCell,
distance, false, d)
|| addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,
distance, d, false)) {
mLauncher.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY);
return;
}
...