1. 程式人生 > >android launcher3拖拽事件響應解析長按事件處理

android launcher3拖拽事件響應解析長按事件處理

        AndroidICS4.0版本的launcher拖拽的流程,基本和2.3的相似。就是比2.3寫的封裝的介面多了一些,比如刪除類的寫法就多了個類。等等。4.0的改變有一些,但是不是特別大。這個月一直在改動Launcher的縮圖的效果,4.0的縮圖的功能沒有實現,還得從2.3的Launcher中摘出來。通過做這個縮圖對Launcher的模組有一點點了解,拿來分享一下Launcher拖拽的工作流程。微笑有圖有真相!吐舌頭

                (1) 先來看看類之間的繼承關係

                           

                                                          圖(1)

               (2)再來看看Launcher拖拽流程的時序圖

               

                                                                       圖(2)

下面咱們分步來解析Launcher拖拽的詳細過程:

step 1 :先來看看Launcher.java這個類的onCreate()方法中的setupViews()方法中的一部分程式碼:

[java] view plaincopyprint?
  1. <strong> </strong><span style=
    "color:#000000;FONT-SIZE: 16px">// Setup the workspace
  2.         mWorkspace.setHapticFeedbackEnabled(false);  
  3.         mWorkspace.setOnLongClickListener(this);  
  4.         mWorkspace.setup(dragController);  
  5.         dragController.addDragListener(mWorkspace);</span>  

Workspace設定長按事件的監聽交給了Launcher.java這個類了。所以在主屏上長按事件會走到Launcher.java----->

onLongClick()這個方法中去;

step 2 :接著我們來看看Launcher.java中onLongClick()的程式碼:

[java] view plaincopyprint?
  1. publicboolean onLongClick(View v) {  
  2.          ··············  
  3.  // The hotseat touch handling does not go through Workspace, and we always allow long press
  4.         // on hotseat items.
  5.         final View itemUnderLongClick = longClickCellInfo.cell;  
  6.         boolean allowLongPress = isHotseatLayout(v) || mWorkspace.allowLongPress();  
  7.         if (allowLongPress && !mDragController.isDragging()) {  
  8.             if (itemUnderLongClick == null) {  
  9.                 // User long pressed on empty space
  10.                 mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,  
  11.                         HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);  
  12.                 startWallpaper();  
  13.             } else {  
  14.                 if (!(itemUnderLongClick instanceof Folder)) {  
  15.                     // User long pressed on an item
  16.                     mWorkspace.startDrag(longClickCellInfo);  
  17.                 }  
  18.             }  
  19.         }  
  20.         returntrue;  
  21.     }  

通過itemUnderLongClick == null 來判斷,在螢幕上觸發長按事件是否選中了shortcut或者widget。如果為空,就啟動桌面的桌布,else,就把拖拽事件往Workspace.java這個類傳遞。

Step 3 :通過mWorkspace.startDrag(longClickCellInfo),把長按事件傳遞給workspace來處理,具體來看程式碼:

[java] view plaincopyprint?
  1. void startDrag(CellLayout.CellInfo cellInfo) {  
  2.      View child = cellInfo.cell;  
  3.      // Make sure the drag was started by a long press as opposed to a long click.
  4.      if (!child.isInTouchMode()) {  
  5.          return;  
  6.      }  
  7.      mDragInfo = cellInfo;  
  8.      //隱藏拖拽的child
  9.      child.setVisibility(GONE);  
  10.      child.clearFocus();  
  11.      child.setPressed(false);  
  12.      final Canvas canvas = new Canvas();  
  13.      // We need to add extra padding to the bitmap to make room for the glow effect
  14.      finalint bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;  
  15.      // The outline is used to visualize where the item will land if dropped
  16.      mDragOutline = createDragOutline(child, canvas, bitmapPadding);  
  17.      beginDragShared(child, this);  
  18.  }  

上面的程式碼主要做的工作是:把正在拖拽的這個view隱藏掉,在主螢幕上繪製一個藍色的,大小和圖示相似的一個邊框,以表示能在主屏的這個位置放置。

Step 4 :接著呼叫beginDragShared(child, this)這個方法,程式碼如下:

[java] view plaincopyprint?
  1. publicvoid beginDragShared(View child, DragSource source) {  
  2.     ··· ···  
  3. // Clear the pressed state if necessary
  4.         if (child instanceof BubbleTextView) {  
  5.             BubbleTextView icon = (BubbleTextView) child;  
  6.             icon.clearPressedOrFocusedBackground();  
  7.         }  
  8.         mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),  
  9.                 DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect);  
  10.         b.recycle();  
  11.     }  

這個方法做的工作是:開始進行拖拽,繪製正在拖拽的圖片,把拖拽的事件交給DragController來處理。

Step 5 :接著來看看mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(), DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect)這個方法,程式碼如下:

[java] view plaincopyprint?
  1. publicvoid startDrag(Bitmap b, int dragLayerX, int dragLayerY,  
  2.             DragSource source, Object dragInfo, int dragAction, Point dragOffset, Rect dragRegion) {  
  3. ··· ···  
  4.  mDragObject.dragComplete = false;  
  5.         mDragObject.xOffset = mMotionDownX - (dragLayerX + dragRegionLeft);  
  6.         mDragObject.yOffset = mMotionDownY - (dragLayerY + dragRegionTop);  
  7.         mDragObject.dragSource = source;  
  8.         mDragObject.dragInfo = dragInfo;  
  9. mVibrator.vibrate(VIBRATE_DURATION);  
  10.         final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX,  
  11.                 registrationY, 00, b.getWidth(), b.getHeight());  
  12.         if (dragOffset != null) {  
  13.             dragView.setDragVisualizeOffset(new Point(dragOffset));  
  14.         }  
  15.         if (dragRegion != null) {  
  16.             dragView.setDragRegion(new Rect(dragRegion));  
  17.         }  
  18.         dragView.show(mMotionDownX, mMotionDownY);  
  19.         handleMoveEvent(mMotionDownX, mMotionDownY);  
  20.     }  

這個方法的作用是:計算要拖拽的view的大小,顯示在workspace上,dragView.show(mMotionDownX, mMotionDownY);這個show()會根據手指的移動而移動的。然後在通過handleMoveEvent()方法來分發拖拽的目標到底在哪個目標上。DropTarget一共有3個:workspace,ButtonDropTarget(刪除類),Folder;他們分別實現了DropTarget這個介面。

下面來看看這個介面有一下幾個方法:

[java] view plaincopyprint?
  1. boolean isDropEnabled();  
  2. void onDrop(DragObject dragObject);  
  3.     void onDragEnter(DragObject dragObject);  
  4.     void onDragOver(DragObject dragObject);  
  5.     void onDragExit(DragObject dragObject);  
  6. DropTarget getDropTargetDelegate(DragObject dragObject);  
  7. boolean acceptDrop(DragObject dragObject);  
  8.     // These methods are implemented in Views
  9.     void getHitRect(Rect outRect);  
  10.     void getLocationInDragLayer(int[] loc);  <