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

创建一个拖动的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" );
         }
 
         // 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;
 
         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);
 
         // Drop on someone?
         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;
 
         // 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
         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:
             // 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 ;
         case MotionEvent.ACTION_MOVE:
             handleMoveEvent(dragLayerX, dragLayerY);
             break ;
         case MotionEvent.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 ;
         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);
 
         // 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;
 
         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 ) {
                 // Move internally
                 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 ;
                 // 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
                     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;
                         // 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 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();
 
             // Prepare it to be animated into its new position
             // This must be called after the view has been re-parented
             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 );
 
             // Hide folder title in the hotseat
             if (child instanceof FolderIcon) {
                 ((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 (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 ;
         }
 
         // Get the canonical child id to uniquely represent this view in this screen
         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)) {
             // 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 (!(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;
 
         // 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);
 
             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) {
         // Return early if this is not initiated from a touch
         if (!v.isInTouchMode()) return false ;
         // Return early if we are still animating the pages
         if (mNextPage != INVALID_PAGE) return false ;
         // When we have exited all apps or are in transition, disregard long clicks
         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) {
         // Dismiss the cling
         mLauncher.dismissAllAppsCling( null );
 
         if (! super .beginDragging(v)) return false ;
 
         // Go into spring loaded mode (must happen before we startDrag())
         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();
 
         // We need to add extra padding to the bitmap to make room for the glow effect
         final int bitmapPadding = 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>
<pre class = "brush:java;" >    public void beginDragShared(View child, DragSource source) {
         Resources r = getResources();
 
         // We need to add extra padding to the bitmap to make room for the glow effect
         final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
 
         // The drag bitmap follows the touch point around on the screen
         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;
             // 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(-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);
         }
 
         // 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);
         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() {
                     // When dragging and dropping from customization tray, we deal with creating
                     // widgets/shortcuts/folders in a slightly different way
                     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();
                 }
             };
 
             // 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);
             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());
             // 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) {
             case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
             case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                 if (info.container == NO_ID && info instanceof ApplicationInfo) {
                     // Came from all apps -- make a copy
                     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);
             }
 
             // 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>
<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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值