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 = sp

你可能感兴趣的:(launcher点击,加载,拖动图标过程三)