launcher点击,加载,拖动图标过程三

来源:互联网 发布:淘宝网披肩女装 编辑:程序博客网 时间:2024/06/04 23:21
创建一个拖动的Bitmap这个和刚才的mDragOutline不同,这个Bitmap透明度、大小等等有变化的。然后就是
<p></p>
<p></p>
<preclass="brush:java;">        mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
                DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect);</pre><br>
也就是
<p></p>
<p></p>
<preclass="brush:java;">   publicvoidstartDrag(Bitmap b, intdragLayerX,intdragLayerY,
            DragSource source, Object dragInfo, intdragAction, Point dragOffset, Rect dragRegion) {
        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);
        }
 
        finalintregistrationX = mMotionDownX - dragLayerX;
        finalintregistrationY = mMotionDownY - dragLayerY;
 
        finalintdragRegionLeft = dragRegion == null?0: dragRegion.left;
        finalintdragRegionTop = dragRegion == null?0: dragRegion.top;
 
        mDragging = true;
 
        mDragObject = newDropTarget.DragObject();
 
        mDragObject.dragComplete = false;
        mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);
        mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);
        mDragObject.dragSource = source;
        mDragObject.dragInfo = dragInfo;
 
        mVibrator.vibrate(VIBRATE_DURATION);
 
        finalDragView dragView = mDragObject.dragView = newDragView(mLauncher, b, registrationX,
                registrationY,0,0, b.getWidth(), b.getHeight());
 
        if(dragOffset != null) {
            dragView.setDragVisualizeOffset(newPoint(dragOffset));
        }
        if(dragRegion != null) {
            dragView.setDragRegion(newRect(dragRegion));
        }
 
        dragView.show(mMotionDownX, mMotionDownY);
        handleMoveEvent(mMotionDownX, mMotionDownY);
    }</pre><br>
创建一个DragView然后显示dragView.show,长按的时候会震动一下也就是在这里mVibrator.vibrate(VIBRATE_DURATION),最终handleMoveEvent(mMotionDownX, mMotionDownY)也就是
<p></p>
<p></p>
<preclass="brush:java;">   privatevoidhandleMoveEvent(intx,inty) {
        mDragObject.dragView.move(x, y);
 
        // Drop on someone?
        finalint[] 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;
 
        // After a scroll, the touch point will still be in the scroll region.
        // Rather than scrolling immediately, require a bit of twiddling to scroll again
        finalintslop = 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);
                }
            }
        }elseif(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>
<preclass="brush:java;">   publicbooleanonTouchEvent(MotionEvent ev) {
        if(!mDragging) {
            returnfalse;
        }
 
        finalintaction = ev.getAction();
        finalint[] dragLayerPos = getClampedDragLayerPos(ev.getX(), ev.getY());
        finalintdragLayerX = dragLayerPos[0];
        finalintdragLayerY = dragLayerPos[1];
 
        switch(action) {
        caseMotionEvent.ACTION_DOWN:
            // Remember where the motion event started
            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;
        caseMotionEvent.ACTION_MOVE:
            handleMoveEvent(dragLayerX, dragLayerY);
            break;
        caseMotionEvent.ACTION_UP:
            // Ensure that we've processed a move event at the current pointer location.
            handleMoveEvent(dragLayerX, dragLayerY);
 
            mHandler.removeCallbacks(mScrollRunnable);
            if(mDragging) {
                drop(dragLayerX, dragLayerY);
            }
            endDrag();
            break;
        caseMotionEvent.ACTION_CANCEL:
            cancelDrag();
            break;
        }
 
        returntrue;
    }</pre><br>
这里的MotionEvent.ACTION_MOVE消息,一直重复handleMoveEvent,当松手的时候就是MotionEvent.ACTION_UP了。我们还先回到handleMoveEvent看看
<p></p>
<p></p>
<preclass="brush:java;">mDragObject.dragView.move(x, y);</pre><br>
这个就是拖动的过程了,也就是
<p></p>
<p></p>
<preclass="brush:java;">   voidmove(inttouchX,inttouchY) {
        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>
<preclass="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>
<preclass="brush:java;">   privatevoiddrop(floatx,floaty) {
        finalint[] coordinates = mCoordinatesTemp;
        finalDropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates);
 
        mDragObject.x = coordinates[0];
        mDragObject.y = coordinates[1];
        booleanaccepted = 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>
<preclass="brush:java;">   publicvoidonDrop(DragObject d) {
        mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView,
                mDragViewVisualCenter);
 
        // We want the point to be mapped to the dragTarget.
        if(mDragTargetLayout != null) {
            if(mLauncher.isHotseatLayout(mDragTargetLayout)) {
                mapPointFromSelfToSibling(mLauncher.getHotseat(), mDragViewVisualCenter);
            }else{
                mapPointFromSelfToChild(mDragTargetLayout, mDragViewVisualCenter, null);
            }
        }
 
        CellLayout dropTargetLayout = mDragTargetLayout;
 
        intsnapScreen = -1;
        if(d.dragSource != this) {
            finalint[] touchXY = newint[] { (int) mDragViewVisualCenter[0],
                    (int) mDragViewVisualCenter[1] };
            onDropExternal(touchXY, d.dragInfo, dropTargetLayout, false, d);
        }elseif(mDragInfo != null) {
            finalView cell = mDragInfo.cell;
 
            if(dropTargetLayout != null) {
                // Move internally
                booleanhasMovedLayouts = (getParentCellLayoutForView(cell) != dropTargetLayout);
                booleanhasMovedIntoHotseat = mLauncher.isHotseatLayout(dropTargetLayout);
                longcontainer = hasMovedIntoHotseat ?
                        LauncherSettings.Favorites.CONTAINER_HOTSEAT :
                        LauncherSettings.Favorites.CONTAINER_DESKTOP;
                intscreen = (mTargetCell[0] < 0) ?
                        mDragInfo.screen : indexOfChild(dropTargetLayout);
                intspanX = mDragInfo != null? mDragInfo.spanX : 1;
                intspanY = 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);
                // 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, false, d.dragView, null)) {
                    return;
                }
 
                if(addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell, d, false)) {
                    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
                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) {
                        // Reparent the view
                        /* Modify 112809 Spreadst of 112809 Monkey start */
                        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);
                    }
 
                    // update the item's position after drop
                    finalItemInfo 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 &&
                            cellinstanceofLauncherAppWidgetHostView) {
                        finalCellLayout cellLayout = dropTargetLayout;
                        // We post this call so that the widget has a chance to be placed
                        // in its final location
 
                        finalLauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;
                        AppWidgetProviderInfo pinfo = hostView.getAppWidgetInfo();
                        if(pinfo != null&& pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
                            finalRunnable resizeRunnable = newRunnable() {
                                publicvoidrun() {
                                    DragLayer dragLayer = mLauncher.getDragLayer();
                                    dragLayer.addResizeFrame(info, hostView, cellLayout);
                                }
                            };
                            post(newRunnable() {
                                publicvoidrun() {
                                    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(cellinstanceofFolderIcon){
                            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);
                }
            }
 
            finalCellLayout parent = (CellLayout) cell.getParent().getParent();
 
            // Prepare it to be animated into its new position
            // This must be called after the view has been re-parented
            finalRunnable disableHardwareLayersRunnable = newRunnable() {
                @Override
                publicvoidrun() {
                    mAnimatingViewIntoPlace = false;
                    updateChildrenLayersEnabled();
                }
            };
            mAnimatingViewIntoPlace = true;
            if(d.dragView.hasDrawn()) {
                intduration = 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>
<preclass="brush:java;">                        addInScreen(cell, container, screen, mTargetCell[0], mTargetCell[1],
                                mDragInfo.spanX, mDragInfo.spanY);</pre><br>
addInScreen也就是
<p></p>
<p></p>
<preclass="brush:java;">   voidaddInScreen(View child, longcontainer,intscreen,intx,inty,intspanX,intspanY,
            booleaninsert) {
        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;
            }
        }
 
        finalCellLayout layout;
        if(container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
            layout = mLauncher.getHotseat().getLayout();
            child.setOnKeyListener(null);
 
            // Hide folder title in the hotseat
            if(childinstanceofFolderIcon) {
                ((FolderIcon) child).setTextVisible(false);
            }
 
            if(screen < 0) {
                screen = mLauncher.getHotseat().getOrderInHotseat(x, y);
            }else{
                // Note: We do this to ensure that the hotseat is always laid out in the orientation
                // of the hotseat in order regardless of which orientation they were added
                x = mLauncher.getHotseat().getCellXFromOrder(screen);
                y = mLauncher.getHotseat().getCellYFromOrder(screen);
            }
        }else{
            // Show folder title if not in the hotseat
            if(childinstanceofFolderIcon) {
                ((FolderIcon) child).setTextVisible(true);
            }
 
            layout = (CellLayout) getChildAt(screen);
            child.setOnKeyListener(newIconKeyEventListener());
        }
 
        CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams();
        if(lp == null) {
            lp = newCellLayout.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;
        }
 
        // Get the canonical child id to uniquely represent this view in this screen
        intchildId = LauncherModel.getCellLayoutChildId(container, screen, x, y, spanX, spanY);
        booleanmarkCellsAsOccupied = !(child instanceofFolder);
        if(!layout.addViewToCellLayout(child, insert ? 0: -1, childId, lp, markCellsAsOccupied)) {
            // TODO: This branch occurs when the workspace is adding views
            // outside of the defined grid
            // maybe we should be deleting these items from the LauncherModel?
            Log.w(TAG,"Failed to add to item at (" + lp.cellX + ","+ lp.cellY + ") to CellLayout");
        }
 
        if(!(childinstanceofFolder)) {
            child.setHapticFeedbackEnabled(false);
            child.setOnLongClickListener(mLongClickListener);
        }
        if(childinstanceofDropTarget) {
            mDragController.addDropTarget((DropTarget) child);
        }
    }</pre><br>
这里做了一些计算,拖动的是什么,放在哪里等等吧,然后就layout.addViewToCellLayout(child, insert ? 0: -1, childId, lp, markCellsAsOccupied)这里的layout是CellLayout所以layout.addViewToCellLayout也就是
<p></p>
<p></p>
<preclass="brush:java;">   publicbooleanaddViewToCellLayout(
            View child, intindex,intchildId, LayoutParams params, booleanmarkCells) {
        finalLayoutParams lp = params;
 
        // Generate an id for each view, this assumes we have at most 256x256 cells
        // per workspace screen
        if(lp.cellX >= 0&& lp.cellX <= mCountX - 1&& lp.cellY >= 0&& lp.cellY <= mCountY - 1) {
            // If the horizontal or vertical span is set to -1, it is taken to
            // mean that it spans the extent of the CellLayout
            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);
 
            returntrue;
        }
        returnfalse;
    }</pre><br>
也就是mChildren.addView(child, index, lp)了,这里的mChildren也就是CellLayoutChildren,CellLayoutChildren我们前面说过了,就不再说了,至此一个移动过程结束。现在我们回过头来看看如果是从主菜单拖到workspace待机是怎么一个过程,这个过程主要是从主菜单到workspace的转换过程,我们还是从长按事件开始,从主菜单长按事件应该在AppsCustomizePagedView里面,但是这里没有,我们去它的父类PagedViewWithDraggableItems中寻找,也就是
<p></p>
<p></p>
<preclass="brush:java;">   @Override
    publicbooleanonLongClick(View v) {
        // Return early if this is not initiated from a touch
        if(!v.isInTouchMode())returnfalse;
        // Return early if we are still animating the pages
        if(mNextPage != INVALID_PAGE) returnfalse;
        // When we have exited all apps or are in transition, disregard long clicks
        if(!mLauncher.isAllAppsCustomizeOpen() ||
                mLauncher.getWorkspace().isSwitchingState())returnfalse;
 
        returnbeginDragging(v);
    }</pre><br>
也就是beginDragging,beginDragging在其子类AppsCustomizePagedView中重写了,也就是
<p></p>
<p></p>
<preclass="brush:java;">   @Override
    protectedbooleanbeginDragging(View v) {
        // Dismiss the cling
        mLauncher.dismissAllAppsCling(null);
 
        if(!super.beginDragging(v))returnfalse;
 
        // Go into spring loaded mode (must happen before we startDrag())
        mLauncher.enterSpringLoadedDragMode();
 
        if(vinstanceofPagedViewIcon) {
            beginDraggingApplication(v);
        }elseif(v instanceofPagedViewWidget) {
            beginDraggingWidget(v);
        }
        returntrue;
    }</pre><br>
mLauncher.enterSpringLoadedDragMode()是做什么的呢?就是隐藏主菜单,显示workspace待机,这样就从显示上切换到workspace了,但是实质还没切换到workspace,这个后面会讲到,然后就是区分开拖动的是PagedViewIcon(App图标),还是PagedViewWidget(widget图标)。这里我们只看App图标,也就是beginDraggingApplication(v)
<p></p>
<p></p>
<preclass="brush:java;">   privatevoidbeginDraggingApplication(View v) {
        mLauncher.getWorkspace().onDragStartedWithItem(v);
        mLauncher.getWorkspace().beginDragShared(v,this);
    }</pre><br>
这里就是实质上切换到workspace了,先看上面一句mLauncher.getWorkspace().onDragStartedWithItem(v)也就是
<p></p>
<p></p>
<preclass="brush:java;">   publicvoidonDragStartedWithItem(View v) {
        finalCanvas canvas = newCanvas();
 
        // We need to add extra padding to the bitmap to make room for the glow effect
        finalintbitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
 
        // The outline is used to visualize where the item will land if dropped
        mDragOutline = createDragOutline(v, canvas, bitmapPadding);
    }</pre><br>
这里同样创建了一个Bitmap为mDragOutline,和刚才我们讲解workspace拖动一样啦,就不再说了,然后看看下句mLauncher.getWorkspace().beginDragShared(v,this)也就是
<p></p>
<p></p>
<preclass="brush:java;">   publicvoidbeginDragShared(View child, DragSource source) {
        Resources r = getResources();
 
        // We need to add extra padding to the bitmap to make room for the glow effect
        finalintbitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
 
        // The drag bitmap follows the touch point around on the screen
        finalBitmap b = createDragBitmap(child, newCanvas(), bitmapPadding);
 
        finalintbmpWidth = b.getWidth();
 
        mLauncher.getDragLayer().getLocationInDragLayer(child, mTempXY);
        finalintdragLayerX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
        intdragLayerY = mTempXY[1] - bitmapPadding / 2;
 
        Point dragVisualizeOffset = null;
        Rect dragRect = null;
        if(childinstanceofBubbleTextView || child instanceofPagedViewIcon) {
            inticonSize = r.getDimensionPixelSize(R.dimen.app_icon_size);
            inticonPaddingTop = r.getDimensionPixelSize(R.dimen.app_icon_padding_top);
            inttop = child.getPaddingTop();
            intleft = (bmpWidth - iconSize) / 2;
            intright = left + iconSize;
            intbottom = 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 = newPoint(-bitmapPadding / 2, iconPaddingTop - bitmapPadding / 2);
            dragRect = newRect(left, top, right, bottom);
        }elseif(child instanceofFolderIcon) {
            intpreviewSize = r.getDimensionPixelSize(R.dimen.folder_preview_size);
            dragRect = newRect(0,0, child.getWidth(), previewSize);
        }
 
        // Clear the pressed state if necessary
        if(childinstanceofBubbleTextView) {
            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>
<preclass="brush:java;">   privatevoidonDropExternal(finalint[] touchXY, finalObject dragInfo,
            finalCellLayout cellLayout, booleaninsertAtFirst, DragObject d) {
        finalRunnable exitSpringLoadedRunnable = newRunnable() {
            @Override
            publicvoidrun() {
                mLauncher.exitSpringLoadedDragModeDelayed(true,false);
            }
        };
 
        ItemInfo info = (ItemInfo) dragInfo;
        intspanX = info.spanX;
        intspanY = info.spanY;
        if(mDragInfo != null) {
            spanX = mDragInfo.spanX;
            spanY = mDragInfo.spanY;
        }
 
        finallongcontainer = mLauncher.isHotseatLayout(cellLayout) ?
                LauncherSettings.Favorites.CONTAINER_HOTSEAT :
                    LauncherSettings.Favorites.CONTAINER_DESKTOP;
        finalintscreen = indexOfChild(cellLayout);
        if(!mLauncher.isHotseatLayout(cellLayout) && screen != mCurrentPage
                && mState != State.SPRING_LOADED) {
            snapToPage(screen);
        }
 
        if(infoinstanceofPendingAddItemInfo) {
            finalPendingAddItemInfo pendingInfo = (PendingAddItemInfo) dragInfo;
 
            booleanfindNearestVacantCell = 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 = newRunnable() {
                @Override
                publicvoidrun() {
                    // When dragging and dropping from customization tray, we deal with creating
                    // widgets/shortcuts/folders in a slightly different way
                    switch(pendingInfo.itemType) {
                    caseLauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
                        mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) pendingInfo,
                                container, screen, mTargetCell, null);
                        break;
                    caseLauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                        mLauncher.processShortcutFromDrop(pendingInfo.componentName,
                                container, screen, mTargetCell, null);
                        break;
                    default:
                        thrownewIllegalStateException("Unknown item type: " +
                                pendingInfo.itemType);
                    }
                    cellLayout.onDragExit();
                }
            };
 
            // Now we animate the dragView, (ie. the widget or shortcut preview) into its final
            // location and size on the home screen.
            RectF r = estimateItemPosition(cellLayout, pendingInfo,
                    mTargetCell[0], mTargetCell[1], spanX, spanY);
            intloc[] = newint[2];
            loc[0] = (int) r.left;
            loc[1] = (int) r.top;
            setFinalTransitionTransform(cellLayout);
            floatcellLayoutScale =
                    mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(cellLayout, loc);
            resetTransitionTransform(cellLayout);
 
            floatdragViewScale =  Math.min(r.width() / d.dragView.getMeasuredWidth(),
                    r.height() / d.dragView.getMeasuredHeight());
            // The animation will scale the dragView about its center, so we need to center about
            // the final location.
            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{
            // This is for other drag/drop cases, like dragging from All Apps
            View view = null;
 
            switch(info.itemType) {
            caseLauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
            caseLauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                if(info.container == NO_ID && info instanceofApplicationInfo) {
                    // Came from all apps -- make a copy
                    info = newShortcutInfo((ApplicationInfo) info);
                }
                view = mLauncher.createShortcut(R.layout.application, cellLayout,
                        (ShortcutInfo) info);
                break;
            caseLauncherSettings.Favorites.ITEM_TYPE_FOLDER:
                view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, cellLayout,
                        (FolderInfo) info, mIconCache);
                break;
            default:
                thrownewIllegalStateException("Unknown item type: " + info.itemType);
            }
 
            // First we find the cell nearest to point at which the item is
            // dropped, without any consideration to whether there is an item there.
            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) {
                // when dragging and dropping, just find the closest free spot
                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) {
                // We wrap the animation call in the temporary set and reset of the current
                // cellLayout to its final transform -- this means we animate the drag view to
                // the correct final location.
                setFinalTransitionTransform(cellLayout);
                mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, view,
                        exitSpringLoadedRunnable);
                resetTransitionTransform(cellLayout);
            }
        }
    }</pre><br>
这里也分为两个部分一部分是PendingAddItemInfo,PendingAddItemInfo是Widget有关的,这里不再详解,而我们的应用图标又会走到
<p></p>
<p></p>
<preclass="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>
0 0
原创粉丝点击