2012-03-07 35 views

回答

0
//DragController 
public class DragController { 
    private static final String TAG = "DragController"; 

    /** Indicates the drag is a move. */ 
    public static int DRAG_ACTION_MOVE = 0; 

    /** Indicates the drag is a copy. */ 
    public static int DRAG_ACTION_COPY = 1; 

    private static final int VIBRATE_DURATION = 35; 

    private static final boolean PROFILE_DRAWING_DURING_DRAG = false; 

    private Context mContext; 
    private Vibrator mVibrator; 

    // temporaries to avoid gc thrash 
    private Rect mRectTemp = new Rect(); 
    private final int[] mCoordinatesTemp = new int[2]; 

    /** Whether or not we're dragging. */ 
    private boolean mDragging; 

    /** X coordinate of the down event. */ 
    private float mMotionDownX; 

    /** Y coordinate of the down event. */ 
    private float mMotionDownY; 

    /** Info about the screen for clamping. */ 
    private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); 

    /** Original view that is being dragged. */ 
    private View mOriginator; 

    /** X offset from the upper-left corner of the cell to where we touched. */ 
    private float mTouchOffsetX; 

    /** Y offset from the upper-left corner of the cell to where we touched. */ 
    private float mTouchOffsetY; 

    /** Where the drag originated */ 
    private DragSource mDragSource; 

    /** The data associated with the object being dragged */ 
    private Object mDragInfo; 

    /** The view that moves around while you drag. */ 
    private DragView mDragView; 

    /** Who can receive drop events */ 
    private ArrayList<DropTarget> mDropTargets = new ArrayList<DropTarget>(); 

    private DragListener mListener; 

    /** The window token used as the parent for the DragView. */ 
    private IBinder mWindowToken; 

    private View mMoveTarget; 

    private DropTarget mLastDropTarget; 

    private InputMethodManager mInputMethodManager; 


    interface DragListener { 


     void onDragStart(DragSource source, Object info, int dragAction); 

     /** 
     * The drag has eneded 
     */ 
     void onDragEnd(); 
    } 

    /** 
    * Used to create a new DragLayer from XML. 
    * 
    * @param context The application's context. 
    */ 
    public DragController(Context context) { 
     mContext = context; 
     mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 

    } 


    public void startDrag(View v, DragSource source, Object dragInfo, int dragAction) { 
     mOriginator = v; 

     Bitmap b = getViewBitmap(v); 

     if (b == null) { 
      // out of memory? 
      return; 
     } 

     int[] loc = mCoordinatesTemp; 
     v.getLocationOnScreen(loc); 
     int screenX = loc[0]; 
     int screenY = loc[1]; 

     startDrag(b, screenX, screenY, 0, 0, b.getWidth(), b.getHeight(), 
       source, dragInfo, dragAction); 

     b.recycle(); 

     if (dragAction == DRAG_ACTION_MOVE) { 
      v.setVisibility(View.GONE); 
     } 
    } 


    public void startDrag(Bitmap b, int screenX, int screenY, 
      int textureLeft, int textureTop, int textureWidth, int textureHeight, 
      DragSource source, Object dragInfo, int dragAction) { 
     if (PROFILE_DRAWING_DURING_DRAG) { 
      android.os.Debug.startMethodTracing("Launcher"); 
     } 

     // Hide soft keyboard, if visible 
     if (mInputMethodManager == null) { 
      mInputMethodManager = (InputMethodManager) 
        mContext.getSystemService(Context.INPUT_METHOD_SERVICE); 
     } 
     mInputMethodManager.hideSoftInputFromWindow(mWindowToken, 0); 

     if (mListener != null) { 
      mListener.onDragStart(source, dragInfo, dragAction); 
     } 

     int registrationX = ((int)mMotionDownX) - screenX; 
     int registrationY = ((int)mMotionDownY) - screenY; 

     mTouchOffsetX = mMotionDownX - screenX; 
     mTouchOffsetY = mMotionDownY - screenY; 

     mDragging = true; 
     mDragSource = source; 
     mDragInfo = dragInfo; 

     mVibrator.vibrate(VIBRATE_DURATION); 
     DragView dragView = mDragView = new DragView(mContext, b, registrationX, registrationY, 
       textureLeft, textureTop, textureWidth, textureHeight); 
     dragView.show(mWindowToken, (int)mMotionDownX, (int)mMotionDownY); 
    } 

    /** 
    * Draw the view into a bitmap. 
    */ 
    private Bitmap getViewBitmap(View v) { 
     v.clearFocus(); 
     v.setPressed(false); 

     boolean willNotCache = v.willNotCacheDrawing(); 
     v.setWillNotCacheDrawing(false); 

     // Reset the drawing cache background color to fully transparent 
     // for the duration of this operation 
     int color = v.getDrawingCacheBackgroundColor(); 
     v.setDrawingCacheBackgroundColor(0); 

     if (color != 0) { 
      v.destroyDrawingCache(); 
     } 
     v.buildDrawingCache(); 
     Bitmap cacheBitmap = v.getDrawingCache(); 
     if (cacheBitmap == null) { 
      Log.e(TAG, "failed getViewBitmap(" + v + ")", new RuntimeException()); 
      return null; 
     } 

     Bitmap bitmap = Bitmap.createBitmap(cacheBitmap); 

     // Restore the view 
     v.destroyDrawingCache(); 
     v.setWillNotCacheDrawing(willNotCache); 
     v.setDrawingCacheBackgroundColor(color); 

     return bitmap; 
    } 


    public boolean dispatchKeyEvent(KeyEvent event) { 
     return mDragging; 
    } 

    /** 
    * Stop dragging without dropping. 
    */ 
    public void cancelDrag() { 
     endDrag(); 
    } 

    private void endDrag() { 
     if (mDragging) { 
      mDragging = false; 
      if (mOriginator != null) { 
       mOriginator.setVisibility(View.VISIBLE); 
      } 
      if (mListener != null) { 
       mListener.onDragEnd(); 
      } 
      if (mDragView != null) { 
       mDragView.remove(); 
       mDragView = null; 
      } 
     } 
    } 

    /** 
    * Call this from a drag source view. 
    */ 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     final int action = ev.getAction(); 

     if (action == MotionEvent.ACTION_DOWN) { 
      recordScreenSize(); 
     } 

     final int screenX = clamp((int)ev.getRawX(), 0, mDisplayMetrics.widthPixels); 
     final int screenY = clamp((int)ev.getRawY(), 0, mDisplayMetrics.heightPixels); 

     switch (action) { 
      case MotionEvent.ACTION_MOVE: 
       break; 

      case MotionEvent.ACTION_DOWN: 
       // Remember location of down touch 
       mMotionDownX = screenX; 
       mMotionDownY = screenY; 
       mLastDropTarget = null; 
       break; 

      case MotionEvent.ACTION_CANCEL: 
      case MotionEvent.ACTION_UP: 
       if (mDragging) { 
        drop(screenX, screenY); 
       } 
       endDrag(); 
       break; 
     } 

     return mDragging; 
    } 

    /** 
    * Sets the view that should handle move events. 
    */ 
    void setMoveTarget(View view) { 
     mMoveTarget = view; 
    }  

    public boolean dispatchUnhandledMove(View focused, int direction) { 
     return mMoveTarget != null && mMoveTarget.dispatchUnhandledMove(focused, direction); 
    } 

    /** 
    * Call this from a drag source view. 
    */ 
    public boolean onTouchEvent(MotionEvent ev) { 
     if (!mDragging) { 
      return false; 
     } 

     final int action = ev.getAction(); 
     final int screenX = clamp((int)ev.getRawX(), 0, mDisplayMetrics.widthPixels); 
     final int screenY = clamp((int)ev.getRawY(), 0, mDisplayMetrics.heightPixels); 

     switch (action) { 
     case MotionEvent.ACTION_DOWN: 
      // Remember where the motion event started 
      mMotionDownX = screenX; 
      mMotionDownY = screenY; 
      break; 
     case MotionEvent.ACTION_MOVE: 
      // Update the drag view. Don't use the clamped pos here so the dragging looks 
      // like it goes off screen a little, intead of bumping up against the edge. 
      mDragView.move((int)ev.getRawX(), (int)ev.getRawY()); 
      // Drop on someone? 
      final int[] coordinates = mCoordinatesTemp; 
      DropTarget dropTarget = findDropTarget(screenX, screenY, coordinates); 
      if (dropTarget != null) { 
       if (mLastDropTarget == dropTarget) { 
        dropTarget.onDragOver(mDragSource, coordinates[0], coordinates[1], 
         (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo); 
       } else { 
        if (mLastDropTarget != null) { 
         mLastDropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1], 
          (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo); 
        } 
        dropTarget.onDragEnter(mDragSource, coordinates[0], coordinates[1], 
         (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo); 
       } 
      } else { 
       if (mLastDropTarget != null) { 
        mLastDropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1], 
         (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo); 
       } 
      } 
      mLastDropTarget = dropTarget; 

      /* The original Launcher activity supports a delete region and scrolling. 
       It is not needed in this example. 

      // Scroll, maybe, but not if we're in the delete region. 
      boolean inDeleteRegion = false; 
      if (mDeleteRegion != null) { 
       inDeleteRegion = mDeleteRegion.contains(screenX, screenY); 
      } 
      //Log.d(TAG, "inDeleteRegion=" + inDeleteRegion + " screenX=" + screenX 
      //  + " mScrollZone=" + mScrollZone); 
      if (!inDeleteRegion && screenX < mScrollZone) { 
       if (mScrollState == SCROLL_OUTSIDE_ZONE) { 
        mScrollState = SCROLL_WAITING_IN_ZONE; 
        mScrollRunnable.setDirection(SCROLL_LEFT); 
        mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY); 
       } 
      } else if (!inDeleteRegion && screenX > scrollView.getWidth() - mScrollZone) { 
       if (mScrollState == SCROLL_OUTSIDE_ZONE) { 
        mScrollState = SCROLL_WAITING_IN_ZONE; 
        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); 
       } 
      } 
      */ 
      break; 
     case MotionEvent.ACTION_UP: 
      if (mDragging) { 
       drop(screenX, screenY); 
      } 
      endDrag(); 

      break; 
     case MotionEvent.ACTION_CANCEL: 
      cancelDrag(); 
     } 

     return true; 
    } 

    private boolean drop(float x, float y) { 

     final int[] coordinates = mCoordinatesTemp; 
     DropTarget dropTarget = findDropTarget((int) x, (int) y, coordinates); 

     if (dropTarget != null) { 
      dropTarget.onDragExit(mDragSource, coordinates[0], coordinates[1], 
        (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo); 
      if (dropTarget.acceptDrop(mDragSource, coordinates[0], coordinates[1], 
        (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo)) { 
       dropTarget.onDrop(mDragSource, coordinates[0], coordinates[1], 
         (int) mTouchOffsetX, (int) mTouchOffsetY, mDragView, mDragInfo); 
       mDragSource.onDropCompleted((View) dropTarget, true); 
       return true; 
      } else { 
       mDragSource.onDropCompleted((View) dropTarget, false); 
       return true; 
      } 
     } 
     return false; 
    } 

    private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) { 
     final Rect r = mRectTemp; 

     final ArrayList<DropTarget> dropTargets = mDropTargets; 
     final int count = dropTargets.size(); 
     for (int i=count-1; i>=0; i--) { 
      final DropTarget target = dropTargets.get(i); 
      target.getHitRect(r); 
      target.getLocationOnScreen(dropCoordinates); 
      r.offset(dropCoordinates[0] - target.getLeft(), dropCoordinates[1] - target.getTop()); 
      if (r.contains(x, y)) { 
       dropCoordinates[0] = x - dropCoordinates[0]; 
       dropCoordinates[1] = y - dropCoordinates[1]; 
       return target; 
      } 
     } 
     return null; 
    } 

    /** 
    * Get the screen size so we can clamp events to the screen size so even if 
    * you drag off the edge of the screen, we find something. 
    */ 
    private void recordScreenSize() { 
     ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)) 
       .getDefaultDisplay().getMetrics(mDisplayMetrics); 
    } 

    /** 
    * Clamp val to be &gt;= min and &lt; max. 
    */ 
    private static int clamp(int val, int min, int max) { 
     if (val < min) { 
      return min; 
     } else if (val >= max) { 
      return max - 1; 
     } else { 
      return val; 
     } 
    } 

    public void setWindowToken(IBinder token) { 
     mWindowToken = token; 
    } 

    /** 
    * Sets the drag listner which will be notified when a drag starts or ends. 
    */ 
    public void setDragListener(DragListener l) { 
     mListener = l; 
    } 

    /** 
    * Remove a previously installed drag listener. 
    */ 
    public void removeDragListener(DragListener l) { 
     mListener = null; 
    } 

    /** 
    * Add a DropTarget to the list of potential places to receive drop events. 
    */ 
    public void addDropTarget(DropTarget target) { 
     mDropTargets.add(target); 
    } 

    /** 
    * Don't send drop events to <em>target</em> any more. 
    */ 
    public void removeDropTarget(DropTarget target) { 
     mDropTargets.remove(target); 
    } 

} 




//DragLayer 



public class DragLayer extends MyAbsoluteLayout 
    implements DragSource, DropTarget 
{ 
    DragController mDragController; 


    public DragLayer (Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public void setDragController(DragController controller) { 
     mDragController = controller; 
    } 

    @Override 
    public boolean dispatchKeyEvent(KeyEvent event) { 
     return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event); 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     return mDragController.onInterceptTouchEvent(ev); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent ev) { 
     return mDragController.onTouchEvent(ev); 
    } 

    @Override 
    public boolean dispatchUnhandledMove(View focused, int direction) { 
     return mDragController.dispatchUnhandledMove(focused, direction); 
    } 



public void onDropCompleted (View target, boolean success) 
{ 
    toast ("DragLayer2.onDropCompleted: " + target.getId() + " Check that the view moved."); 
} 


public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset, 
     DragView dragView, Object dragInfo) 
{ 
    View v = (View) dragInfo; 
    toast ("DragLayer2.onDrop accepts view: " + v.getId() 
      + "x, y, xO, yO :" + new Integer (x) + ", " + new Integer (y) + ", " 
      + new Integer (xOffset) + ", " + new Integer (yOffset)); 

    int w = v.getWidth(); 
    int h = v.getHeight(); 
    int left = x - xOffset; 
    int top = y - yOffset; 
    DragLayer.LayoutParams lp = new DragLayer.LayoutParams (w, h, left, top); 
    this.updateViewLayout(v, lp); 
} 

public void onDragEnter(DragSource source, int x, int y, int xOffset, int yOffset, 
     DragView dragView, Object dragInfo) 
{ 
} 

public void onDragOver(DragSource source, int x, int y, int xOffset, int yOffset, 
     DragView dragView, Object dragInfo) 
{ 
} 

public void onDragExit(DragSource source, int x, int y, int xOffset, int yOffset, 
     DragView dragView, Object dragInfo) 
{ 
} 


public boolean acceptDrop(DragSource source, int x, int y, int xOffset, int yOffset, 
     DragView dragView, Object dragInfo) 
{ 
    return true; 
} 


public Rect estimateDropLocation(DragSource source, int x, int y, int xOffset, int yOffset, 
      DragView dragView, Object dragInfo, Rect recycle) 
{ 
    return null; 
} 

public void toast (String msg) 
{ 
    if (!Dashboard.Debugging) return; 
    Toast.makeText (getContext(), msg, Toast.LENGTH_SHORT).show(); 
} // end toast 


} // end class 


//DragSource 

public interface DragSource { 
    void setDragController(DragController dragger); 
    void onDropCompleted(View target, boolean success); 
} 


//DragView 


public class DragView extends View 
{ 
    // Number of pixels to add to the dragged item for scaling. Should be even for pixel alignment. 
    private static final int DRAG_SCALE = 0; // In Launcher, value is 40 

    private Bitmap mBitmap; 
    private Paint mPaint; 
    private int mRegistrationX; 
    private int mRegistrationY; 

    private float mScale; 
    private float mAnimationScale = 1.0f; 

    private WindowManager.LayoutParams mLayoutParams; 
    private WindowManager mWindowManager; 


    public DragView(Context context, Bitmap bitmap, int registrationX, int registrationY, 
      int left, int top, int width, int height) { 
     super(context); 

     // mWindowManager = WindowManagerImpl.getDefault(); 
     mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);   

     Matrix scale = new Matrix(); 
     float scaleFactor = width; 
     scaleFactor = mScale = (scaleFactor + DRAG_SCALE)/scaleFactor; 
     scale.setScale(scaleFactor, scaleFactor); 
     mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height, scale, true); 

     // The point in our scaled bitmap that the touch events are located 
     mRegistrationX = registrationX + (DRAG_SCALE/2); 
     mRegistrationY = registrationY + (DRAG_SCALE/2); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     setMeasuredDimension(mBitmap.getWidth(), mBitmap.getHeight()); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     if (true) { 
      // for debugging 
      Paint p = new Paint(); 
      p.setStyle(Paint.Style.FILL); 
      p.setColor(0x88dd0011); 
      canvas.drawRect(0, 0, getWidth(), getHeight(), p); 
     } 
     float scale = mAnimationScale; 
     if (scale < 0.999f) { // allow for some float error 
      float width = mBitmap.getWidth(); 
      float offset = (width-(width*scale))/2; 
      canvas.translate(offset, offset); 
      canvas.scale(scale, scale); 
     } 
     canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint); 
    } 

    @Override 
    protected void onDetachedFromWindow() { 
     super.onDetachedFromWindow(); 
     mBitmap.recycle(); 
    } 

    public void setPaint(Paint paint) { 
     mPaint = paint; 
     invalidate(); 
    } 

    public void show(IBinder windowToken, int touchX, int touchY) { 
     WindowManager.LayoutParams lp; 
     int pixelFormat; 

     pixelFormat = PixelFormat.TRANSLUCENT; 

     lp = new WindowManager.LayoutParams(
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       touchX-mRegistrationX, touchY-mRegistrationY, 
       WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL, 
       WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN 
        | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS 
        /*| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM*/, 
       pixelFormat); 
//  lp.token = mStatusBarView.getWindowToken(); 
     lp.gravity = Gravity.LEFT | Gravity.TOP; 
     lp.token = windowToken; 
     lp.setTitle("DragView"); 
     mLayoutParams = lp; 

     mWindowManager.addView(this, lp); 

    } 

    void move(int touchX, int touchY) { 
     // This is what was done in the Launcher code. 
     WindowManager.LayoutParams lp = mLayoutParams; 
     lp.x = touchX - mRegistrationX; 
     lp.y = touchY - mRegistrationY; 
     mWindowManager.updateViewLayout(this, lp); 
    } 

    void remove() { 
     mWindowManager.removeView(this); 
    } 
} 


//MainActivity 

private DragController mDragController; 
    private DragLayer mDragLayer; 

//onCreate 
mDragController = new DragController(this); 

     DragController dragController = mDragController; 

     mDragLayer = (DragLayer) findViewById(R.id.drag_layer); 
     mDragLayer.setDragController(dragController); 
     dragController.addDropTarget(mDragLayer); 
RelativeLayout img1=new RelativeLayout(this); 
     DragLayer.LayoutParams lp1 = new DragLayer.LayoutParams(100, 100, 15, 
       15); 
     img1.setLayoutParams(lp1); 

img1.setOnLongClickListener(this); 




public boolean onLongClick(View v) { 
     trace("onLongClick in view: " + v); 

     // Make sure the drag was started by a long press as opposed to a long 
     // click. 
     // (Note: I got this from the Workspace object in the Android Launcher 
     // code. 
     // I think it is here to ensure that the device is still in touch mode 
     // as we start the drag operation.) 
     if (!v.isInTouchMode()) { 
      toast("isInTouchMode returned false. Try touching the view again."); 
      return false; 
     } 
     return startDrag(v); 
    } 
//function 
public boolean startDrag(View v) { 
     // Let the DragController initiate a drag-drop sequence. 
     // I use the dragInfo to pass along the object being dragged. 
     // I'm not sure how the Launcher designers do this. 
     Object dragInfo = v; 
     mDragController.startDrag(v, mDragLayer, dragInfo, 
       DragController.DRAG_ACTION_MOVE); 
     return true; 
    } 
+0

你能否提供所有的類來編譯你的代碼?還將理解的是將不同代碼片段中的不同類分開。提前致謝! – 2014-03-16 20:14:58

相關問題