Launcher App拖拽流程

来源:互联网 发布:淘宝买家秀大尺度男 编辑:程序博客网 时间:2024/05/23 01:26

1,App所在位置是源source,拖拽的目的地是:Target;source和target都是接口
Target接口:主要有四个方法要去实现:

/** * Handle an object being dropped on the DropTarget *  * @param source DragSource where the drag started * @param x X coordinate of the drop location * @param y Y coordinate of the drop location * @param xOffset Horizontal offset with the object being dragged where the original *          touch happened * @param yOffset Vertical offset with the object being dragged where the original *          touch happened * @param dragView The DragView that's being dragged around on screen. * @param dragInfo Data associated with the object being dragged * */void onDrop(DragObject dragObject);void onDragEnter(DragObject dragObject);void onDragOver(DragObject dragObject);void onDragExit(DragObject dragObject);

顾名思义:onDrop:就是在放下后做的操作;
onDragEnter:进入之后的操作;
onDragOver:在目标体之上做的操作;
onDragExit:退出之后的操作;

Source接口:主要有一个方法要实现:

/**
* A callback made back to the source after an item from this source has been dropped on a
* DropTarget.
*/
void onDropCompleted(View target, DragObject d, boolean isFlingToDelete, boolean success);
顾名思义:就是放下完成之后要处理的事情;

App在Workspace上面拖动,所以Workspace既是源也是目的,Workspace实现了这两个接口
public class Workspace extends SmoothPagedView implements DropTarget, DragSource, DragScroller,

当长按一个app是会调用Launcher的onlongclick方法:

 final View itemUnderLongClick = longClickCellInfo.cell;        boolean allowLongPress = isHotseatLayout(v) || mWorkspace.allowLongPress();        if (allowLongPress && !mDragController.isDragging()) {            if (itemUnderLongClick == null) {                // User long pressed on empty space                mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,                        HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);                // Disabling reordering until we sort out some issues.                if (mWorkspace.isInOverviewMode()) {                    mWorkspace.startReordering(v);                } else {                    mWorkspace.enterOverviewMode();                }            } else {                if (!(itemUnderLongClick instanceof Folder)) {                    // User long pressed on an item                    mWorkspace.startDrag(longClickCellInfo);                }            }        }
 最终会进入workspace的startDrag方法会把信息传递过来;
     void startDrag(CellLayout.CellInfo cellInfo) {        View child = cellInfo.cell;        // Make sure the drag was started by a long press as opposed to a long click.        if (!child.isInTouchMode()) {            return;        }        mDragInfo = cellInfo;        child.setVisibility(INVISIBLE);        CellLayout layout = (CellLayout) child.getParent().getParent();        layout.prepareChildForDrag(child);        child.clearFocus();        child.setPressed(false);        final Canvas canvas = new Canvas();        // The outline is used to visualize where the item will land if dropped        mDragOutline = createDragOutline(child, canvas, DRAG_BITMAP_PADDING);        beginDragShared(child, this);    }
当开始拖拽的时候:手按下的view会child.setVisibility(INVISIBLE);隐藏掉;  同时会绘制图标的边框线 createDragOutline(child, canvas, DRAG_BITMAP_PADDING); 
    private Bitmap createDragOutline(View v, Canvas canvas, int padding) {        final int outlineColor = getResources().getColor(R.color.outline_color);        final Bitmap b = Bitmap.createBitmap( v.getWidth() + padding, v.getHeight() +                         padding, Bitmap.Config.ARGB_8888);        canvas.setBitmap(b);        drawDragView(v, canvas, padding, true);        mOutlineHelper.applyMediumExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor);        canvas.setBitmap(null);        return b;    } 
绘制完成之后  beginDragShared(child, this);开始拖拽,手下的view传递过去,同时还需要一个源;
    public void beginDragShared(View child, DragSource source) {        // The drag bitmap follows the touch point around on the screen        final Bitmap b = createDragBitmap(child, new Canvas(), DRAG_BITMAP_PADDING);        final int bmpWidth = b.getWidth();        final int bmpHeight = b.getHeight();        float scale = mLauncher.getDragLayer().getLocationInDragLayer(child, mTempXY);        int dragLayerX =                Math.round(mTempXY[0] - (bmpWidth - scale * child.getWidth()) / 2);        int dragLayerY =                Math.round(mTempXY[1] - (bmpHeight - scale * bmpHeight) / 2                        - DRAG_BITMAP_PADDING / 2);        LauncherAppState app = LauncherAppState.getInstance();        DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();        Point dragVisualizeOffset = null;        Rect dragRect = null;        if (child instanceof BubbleTextView || child instanceof PagedViewIcon) {            int iconSize = grid.iconSizePx;            int top = child.getPaddingTop();            int left = (bmpWidth - iconSize) / 2;            int right = left + iconSize;            int bottom = top + iconSize;            dragLayerY += top;            // Note: The drag region is used to calculate drag layer offsets, but the            // dragVisualizeOffset in addition to the dragRect (the size) to position the outline.            dragVisualizeOffset = new Point(-DRAG_BITMAP_PADDING / 2, DRAG_BITMAP_PADDING / 2);            dragRect = new Rect(left, top, right, bottom);        } else if (child instanceof FolderIcon) {            int previewSize = grid.folderIconSizePx;            dragRect = new Rect(0, child.getPaddingTop(), child.getWidth(), previewSize);        }        // Clear the pressed state if necessary        if (child instanceof BubbleTextView) {            BubbleTextView icon = (BubbleTextView) child;            icon.clearPressedOrFocusedBackground();        }        mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),                DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale);        if (child.getParent() instanceof ShortcutAndWidgetContainer) {            mDragSourceInternal = (ShortcutAndWidgetContainer) child.getParent();        }        b.recycle();    }

这个方法就是首先生成一个和隐藏掉的图标一样的图标,将生成的Drawable交给DragController处理,调用 mDragController.startDrag();

 /**     * Starts a drag.     *     * @param b The bitmap to display as the drag image.  It will be re-scaled to the     *          enlarged size.     * @param dragLayerX The x position in the DragLayer of the left-top of the bitmap.     * @param dragLayerY The y position in the DragLayer of the left-top of the bitmap.     * @param source An object representing where the drag originated     * @param dragInfo The data associated with the object that is being dragged     * @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or     *        {@link #DRAG_ACTION_COPY}     * @param dragRegion Coordinates within the bitmap b for the position of item being dragged.     *          Makes dragging feel more precise, e.g. you can clip out a transparent border     */    public void startDrag(Bitmap b, int dragLayerX, int dragLayerY,            DragSource source, Object dragInfo, int dragAction, Point dragOffset, Rect dragRegion,            float initialDragViewScale) {        if (PROFILE_DRAWING_DURING_DRAG) {            android.os.Debug.startMethodTracing("Launcher");        }        // Hide soft keyboard, if visible        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;        final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX,                registrationY, 0, 0, b.getWidth(), b.getHeight(), initialDragViewScale);        if (dragOffset != null) {            dragView.setDragVisualizeOffset(new Point(dragOffset));        }        if (dragRegion != null) {            dragView.setDragRegion(new Rect(dragRegion));        }        mLauncher.getDragLayer().performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);        dragView.show(mMotionDownX, mMotionDownY);        handleMoveEvent(mMotionDownX, mMotionDownY);    }
mDragController.startDrag()的方法主要是做隐藏键盘,注册DragController的一个接口,生成DragView就是把生成的Drawable转化成DragView,将DragView的坐标传给 handleMoveEvent(mMotionDownX, mMotionDownY)方法,同过获得的坐标DragView就可以移动 mDragObject.dragView.move(x, y);然后通过传过来的坐标在Target上找位置
    private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) {        final Rect r = mRectTemp;        final ArrayList<DropTarget> dropTargets = mDropTargets;        final int count = dropTargets.size();        for (int i=count-1; i>=0; i--) {            DropTarget target = dropTargets.get(i);            if (!target.isDropEnabled())                continue;            target.getHitRectRelativeToDragLayer(r);            mDragObject.x = x;            mDragObject.y = y;            if (r.contains(x, y)) {                dropCoordinates[0] = x;                dropCoordinates[1] = y;                mLauncher.getDragLayer().mapCoordInSelfToDescendent((View) target, dropCoordinates);                return target;            }        }        return null;

如果站到位置之后会返回一个target,通过Target判断DropTarget 的状态是在哪一个状态四个状态就是Target接口的四个方法;

private void checkTouchMove(DropTarget dropTarget) {        if (dropTarget != null) {            if (mLastDropTarget != dropTarget) {                if (mLastDropTarget != null) {                    mLastDropTarget.onDragExit(mDragObject);                }                dropTarget.onDragEnter(mDragObject);            }            dropTarget.onDragOver(mDragObject);        } else {            if (mLastDropTarget != null) {                mLastDropTarget.onDragExit(mDragObject);            }        }        mLastDropTarget = dropTarget;    }

如果是这四种状态,它们会不停的切换状态,当你放下时会调用mDragController的drop()方法,

 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, false, accepted);    }

这个方法会通过findDropTarget()方法得到一个DropTarget,如果DropTarget不等于空mDragObject.dragComplete = true;说明拖拽完成,调用dropTarget.onDragExit(mDragObject);,判断如果dropTarget.acceptDrop(mDragObject),Target接不接受这个view。方法如下:

 /**     * {@inheritDoc}     */    public boolean acceptDrop(DragObject d) {        // If it's an external drop (e.g. from All Apps), check if it should be accepted        CellLayout dropTargetLayout = mDropToLayout;        if (d.dragSource != this) {            // Don't accept the drop if we're not over a screen at time of drop            if (dropTargetLayout == null) {                return false;            }            if (!transitionStateShouldAllowDrop()) return false;            mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset,                    d.dragView, mDragViewVisualCenter);            // We want the point to be mapped to the dragTarget.            if (mLauncher.isHotseatLayout(dropTargetLayout)) {                mapPointFromSelfToHotseatLayout(mLauncher.getHotseat(), mDragViewVisualCenter);            } else {                mapPointFromSelfToChild(dropTargetLayout, mDragViewVisualCenter, null);            }            int spanX = 1;            int spanY = 1;            if (mDragInfo != null) {                final CellLayout.CellInfo dragCellInfo = mDragInfo;                spanX = dragCellInfo.spanX;                spanY = dragCellInfo.spanY;            } else {                final ItemInfo dragInfo = (ItemInfo) d.dragInfo;                spanX = dragInfo.spanX;                spanY = dragInfo.spanY;            }            int minSpanX = spanX;            int minSpanY = spanY;            if (d.dragInfo instanceof PendingAddWidgetInfo) {                minSpanX = ((PendingAddWidgetInfo) d.dragInfo).minSpanX;                minSpanY = ((PendingAddWidgetInfo) d.dragInfo).minSpanY;            }            mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],                    (int) mDragViewVisualCenter[1], minSpanX, minSpanY, dropTargetLayout,                    mTargetCell);            float distance = dropTargetLayout.getDistanceFromCell(mDragViewVisualCenter[0],                    mDragViewVisualCenter[1], mTargetCell);            if (willCreateUserFolder((ItemInfo) d.dragInfo, dropTargetLayout,                    mTargetCell, distance, true)) {                return true;            }            if (willAddToExistingUserFolder((ItemInfo) d.dragInfo, dropTargetLayout,                    mTargetCell, distance)) {                return true;            }            int[] resultSpan = new int[2];            mTargetCell = dropTargetLayout.createArea((int) mDragViewVisualCenter[0],                    (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY,                    null, mTargetCell, resultSpan, CellLayout.MODE_ACCEPT_DROP);            boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0;            // Don't accept the drop if there's no room for the item            if (!foundCell) {                // Don't show the message if we are dropping on the AllApps button and the hotseat                // is full                boolean isHotseat = mLauncher.isHotseatLayout(dropTargetLayout);                if (mTargetCell != null && isHotseat) {                    Hotseat hotseat = mLauncher.getHotseat();                    if (hotseat.isAllAppsButtonRank(                            hotseat.getOrderInHotseat(mTargetCell[0], mTargetCell[1]))) {                        return false;                    }                }                mLauncher.showOutOfSpaceMessage(isHotseat);                return false;            }        }

这个方法是返回一个boolean值,首先会判断source是不是自己,是自己就直接返回true,不是自己就是继续做判断,会去找位置调用

private int[] findNearestArea(int pixelX, int pixelY,            int spanX, int spanY, CellLayout layout, int[] recycle) {        return layout.findNearestArea(                pixelX, pixelY, spanX, spanY, recycle);    }

找到位置之后 boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0;

会得到一个boolean值foundCell ,

if (!foundCell) {                // Don't show the message if we are dropping on the AllApps button and the hotseat                // is full                boolean isHotseat = mLauncher.isHotseatLayout(dropTargetLayout);                if (mTargetCell != null && isHotseat) {                    Hotseat hotseat = mLauncher.getHotseat();                    if (hotseat.isAllAppsButtonRank(                            hotseat.getOrderInHotseat(mTargetCell[0], mTargetCell[1]))) {                        return false;                    }                }                mLauncher.showOutOfSpaceMessage(isHotseat);                return false;            }

判断是否在hotseat位置,是否在Allapp的按钮上就是进入主页面的按钮上;

最终会到 dropTarget的Ondrop方法

if (dropTarget.acceptDrop(mDragObject)) {                dropTarget.onDrop(mDragObject);                accepted = true; }

到workspace的ondrop方法看看(在桌面拖动,所以会调用workspace的ondrop方法,那个Target就是Workspace),

  public void onDrop(final DragObject d) {        mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView,                mDragViewVisualCenter);        CellLayout dropTargetLayout = mDropToLayout;        // We want the point to be mapped to the dragTarget.        if (dropTargetLayout != null) {            if (mLauncher.isHotseatLayout(dropTargetLayout)) {                mapPointFromSelfToHotseatLayout(mLauncher.getHotseat(), mDragViewVisualCenter);            } else {                mapPointFromSelfToChild(dropTargetLayout, mDragViewVisualCenter, null);            }        }        int snapScreen = -1;        boolean resizeOnDrop = false;        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;            Runnable resizeRunnable = null;            if (dropTargetLayout != null && !d.cancelled) {                // Move internally                boolean hasMovedLayouts = (getParentCellLayoutForView(cell) != dropTargetLayout);                boolean hasMovedIntoHotseat = mLauncher.isHotseatLayout(dropTargetLayout);                long container = hasMovedIntoHotseat ?                        LauncherSettings.Favorites.CONTAINER_HOTSEAT :                        LauncherSettings.Favorites.CONTAINER_DESKTOP;                long 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.getDistanceFromCell(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 (!mInScrollArea && createUserFolderIfNecessary(cell, container,                        dropTargetLayout, mTargetCell, distance, false, d.dragView, null)) {                    stripEmptyScreens();                    return;                }                if (addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,                        distance, d, false)) {                    stripEmptyScreens();                    return;                }                // Aside from the special case where we're dropping a shortcut onto a shortcut,                // we need to find the nearest cell location that is vacant                ItemInfo item = (ItemInfo) d.dragInfo;                int minSpanX = item.spanX;                int minSpanY = item.spanY;                if (item.minSpanX > 0 && item.minSpanY > 0) {                    minSpanX = item.minSpanX;                    minSpanY = item.minSpanY;                }                int[] resultSpan = new int[2];                mTargetCell = dropTargetLayout.createArea((int) mDragViewVisualCenter[0],                        (int) mDragViewVisualCenter[1], minSpanX, minSpanY, spanX, spanY, cell,                        mTargetCell, resultSpan, CellLayout.MODE_ON_DROP);                boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0;                // if the widget resizes on drop                if (foundCell && (cell instanceof AppWidgetHostView) &&                        (resultSpan[0] != item.spanX || resultSpan[1] != item.spanY)) {                    resizeOnDrop = true;                    item.spanX = resultSpan[0];                    item.spanY = resultSpan[1];                    AppWidgetHostView awhv = (AppWidgetHostView) cell;                    AppWidgetResizeFrame.updateWidgetSizeRanges(awhv, mLauncher, resultSpan[0],                            resultSpan[1]);                }                if (getScreenIdForPageIndex(mCurrentPage) != screenId && !hasMovedIntoHotseat) {                    snapScreen = getPageIndexForScreenId(screenId);                    snapToPage(snapScreen);                }                if (foundCell) {                    final ItemInfo info = (ItemInfo) cell.getTag();                    if (hasMovedLayouts) {                        // Reparent the view                        getParentCellLayoutForView(cell).removeView(cell);                        addInScreen(cell, container, screenId, mTargetCell[0], mTargetCell[1],                                info.spanX, info.spanY);                    }                    // update the item's position after drop                    CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();                    lp.cellX = lp.tmpCellX = mTargetCell[0];                    lp.cellY = lp.tmpCellY = mTargetCell[1];                    lp.cellHSpan = item.spanX;                    lp.cellVSpan = item.spanY;                    lp.isLockedToGrid = true;                    cell.setId(LauncherModel.getCellLayoutChildId(container, mDragInfo.screenId,                            mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));                    if (container != LauncherSettings.Favorites.CONTAINER_HOTSEAT &&                            cell instanceof LauncherAppWidgetHostView) {                        final CellLayout cellLayout = dropTargetLayout;                        // We post this call so that the widget has a chance to be placed                        // in its final location                        final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;                        AppWidgetProviderInfo pinfo = hostView.getAppWidgetInfo();                        if (pinfo != null &&                                pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {                            final Runnable addResizeFrame = new Runnable() {                                public void run() {                                    DragLayer dragLayer = mLauncher.getDragLayer();                                    dragLayer.addResizeFrame(info, hostView, cellLayout);                                }                            };                            resizeRunnable = (new Runnable() {                                public void run() {                                    if (!isPageMoving()) {                                        addResizeFrame.run();                                    } else {                                        mDelayedResizeRunnable = addResizeFrame;                                    }                                }                            });                        }                    }                    LauncherModel.modifyItemInDatabase(mLauncher, info, container, screenId, lp.cellX,                            lp.cellY, item.spanX, item.spanY);                } else {                    // If we can't find a drop location, we return the item to its original position                    CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();                    mTargetCell[0] = lp.cellX;                    mTargetCell[1] = lp.cellY;                    CellLayout layout = (CellLayout) cell.getParent().getParent();                    layout.markCellsAsOccupiedForView(cell);                }            }            final CellLayout parent = (CellLayout) cell.getParent().getParent();            final Runnable finalResizeRunnable = resizeRunnable;            // Prepare it to be animated into its new position            // This must be called after the view has been re-parented            final Runnable onCompleteRunnable = new Runnable() {                @Override                public void run() {                    mAnimatingViewIntoPlace = false;                    updateChildrenLayersEnabled(false);                    if (finalResizeRunnable != null) {                        finalResizeRunnable.run();                    }                    stripEmptyScreens();                }            };            mAnimatingViewIntoPlace = true;            if (d.dragView.hasDrawn()) {                final ItemInfo info = (ItemInfo) cell.getTag();                if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) {                    int animationType = resizeOnDrop ? ANIMATE_INTO_POSITION_AND_RESIZE :                            ANIMATE_INTO_POSITION_AND_DISAPPEAR;                    animateWidgetDrop(info, parent, d.dragView,                            onCompleteRunnable, animationType, cell, false);                } else {                    int duration = snapScreen < 0 ? -1 : ADJACENT_SCREEN_DROP_DURATION;                    mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell, duration,                            onCompleteRunnable, this);                }            } else {                d.deferDragViewCleanupPostAnimation = false;                cell.setVisibility(VISIBLE);            }            parent.onDropChild(cell);        }    }

方法蛮长的,我们只看重点:

 if (!mInScrollArea && createUserFolderIfNecessary(cell, container,                        dropTargetLayout, mTargetCell, distance, false, d.dragView, null)) {                    stripEmptyScreens();                    return;  }

createUserFolderIfNecessary顾名思义就是两个应用是否合成文件夹;进去里面看看

 boolean createUserFolderIfNecessary(View newView, long container, CellLayout target,            int[] targetCell, float distance, boolean external, DragView dragView,            Runnable postAnimationRunnable) {        if (distance > mMaxDistanceForFolderCreation) return false;        View v = target.getChildAt(targetCell[0], targetCell[1]);        boolean hasntMoved = false;        if (mDragInfo != null) {            CellLayout cellParent = getParentCellLayoutForView(mDragInfo.cell);            hasntMoved = (mDragInfo.cellX == targetCell[0] &&                    mDragInfo.cellY == targetCell[1]) && (cellParent == target);        }        if (v == null || hasntMoved || !mCreateUserFolderOnDrop) return false;        mCreateUserFolderOnDrop = false;        final long screenId = (targetCell == null) ? mDragInfo.screenId : getIdForScreen(target);        boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo);        boolean willBecomeShortcut = (newView.getTag() instanceof ShortcutInfo);        if (aboveShortcut && willBecomeShortcut) {            ShortcutInfo sourceInfo = (ShortcutInfo) newView.getTag();            ShortcutInfo destInfo = (ShortcutInfo) v.getTag();            // if the drag started here, we need to remove it from the workspace            if (!external) {                getParentCellLayoutForView(mDragInfo.cell).removeView(mDragInfo.cell);            }            Rect folderLocation = new Rect();            float scale = mLauncher.getDragLayer().getDescendantRectRelativeToSelf(v, folderLocation);            target.removeView(v);            FolderIcon fi =                mLauncher.addFolder(target, container, screenId, targetCell[0], targetCell[1]);            destInfo.cellX = -1;            destInfo.cellY = -1;            sourceInfo.cellX = -1;            sourceInfo.cellY = -1;            // If the dragView is null, we can't animate            boolean animate = dragView != null;            if (animate) {                fi.performCreateAnimation(destInfo, v, sourceInfo, dragView, folderLocation, scale,                        postAnimationRunnable);            } else {                fi.addItem(destInfo);                fi.addItem(sourceInfo);            }            return true;        }        return false;    }

方法有点长,也只看重点 boolean aboveShortcut = (v.getTag() instanceof ShortcutInfo);
boolean willBecomeShortcut = (newView.getTag() instanceof ShortcutInfo);
就是判断是否是在应用的上面,就是说,你放下的dragview下面是否是ShortcutInfo,而且你手放下的view也是ShortcutInfo,就合成文件夹 FolderIcon fi = mLauncher.addFolder(target, container, screenId, targetCell[0], targetCell[1]);合成文件夹返回true,

继续回到workspace的ondrop方法如果不是创建文件夹;继续往下

 if (addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell,                        distance, d, false)) {                    stripEmptyScreens();                    return;  }

addToExistingFolderIfNecessary 顾名思义:既是加入到已经存在的文件夹

 boolean addToExistingFolderIfNecessary(View newView, CellLayout target, int[] targetCell,            float distance, DragObject d, boolean external) {        if (distance > mMaxDistanceForFolderCreation) return false;        View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);        if (!mAddToExistingFolderOnDrop) return false;        mAddToExistingFolderOnDrop = false;        if (dropOverView instanceof FolderIcon) {            FolderIcon fi = (FolderIcon) dropOverView;            if (fi.acceptDrop(d.dragInfo)) {                fi.onDrop(d);                // if the drag started here, we need to remove it from the workspace                if (!external) {                    getParentCellLayoutForView(mDragInfo.cell).removeView(mDragInfo.cell);                }                return true;            }        }        return false;    }

这个方法就是判断下面的view是否是文件夹,就进入到文件夹的Ondrop方法进行对addItem(item);
是否接受应用,文件夹是否没有销毁,条件成立之后返回true;就加入到文件夹了

继续ondrop方法:

if (foundCell) {                    final ItemInfo info = (ItemInfo) cell.getTag();                    if (hasMovedLayouts) {                        // Reparent the view                        getParentCellLayoutForView(cell).removeView(cell);                        addInScreen(cell, container, screenId, mTargetCell[0], mTargetCell[1],                                info.spanX, info.spanY);  }

如果桌面有位置就会 addInScreen(cell, container, screenId, mTargetCell[0], mTargetCell[1], info.spanX, info.spanY);然后对数据的操作 LauncherModel.modifyItemInDatabase(mLauncher, info, container, screenId, lp.cellX,lp.cellY, item.spanX, item.spanY);

放下完成之后会调用source的onDropCompleted方法做一系列拖拽完成的操作;

if (parentCell != null) {                    parentCell.removeView(mDragInfo.cell); }

会把隐藏的view移除掉

拖拽完成!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

0 0
原创粉丝点击