diff --git a/src/com/android/launcher3/AnotherWindowDropTarget.java b/src/com/android/launcher3/AnotherWindowDropTarget.java new file mode 100644 index 0000000000..aff36ae510 --- /dev/null +++ b/src/com/android/launcher3/AnotherWindowDropTarget.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.content.Context; +import android.graphics.PointF; +import android.graphics.Rect; + +/** + * Drop target used when another window (i.e. another process) has accepted a global system drag. + * If the accepted item was a shortcut, we delete it from Launcher. + */ +public class AnotherWindowDropTarget implements DropTarget { + final Launcher mLauncher; + + AnotherWindowDropTarget (Context context) { mLauncher = (Launcher) context; } + + @Override + public boolean isDropEnabled() { return true; } + + @Override + public void onDrop(DragObject dragObject) { + dragObject.deferDragViewCleanupPostAnimation = false; + LauncherModel.deleteItemFromDatabase(mLauncher, (ShortcutInfo) dragObject.dragInfo); + } + + @Override + public void onDragEnter(DragObject dragObject) {} + + @Override + public void onDragOver(DragObject dragObject) {} + + @Override + public void onDragExit(DragObject dragObject) {} + + @Override + public void onFlingToDelete(DragObject dragObject, PointF vec) {} + + @Override + public boolean acceptDrop(DragObject dragObject) { + return dragObject.dragInfo instanceof ShortcutInfo; + } + + @Override + public void prepareAccessibilityDrop() {} + + // These methods are implemented in Views + @Override + public void getHitRectRelativeToDragLayer(Rect outRect) {} + + @Override + public void getLocationInDragLayer(int[] loc) {} + + @Override + public int getLeft() { return 0; } + + @Override + public int getTop() { return 0; } +} diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java index 410271d297..53e90fcbca 100644 --- a/src/com/android/launcher3/DragController.java +++ b/src/com/android/launcher3/DragController.java @@ -26,6 +26,7 @@ import android.graphics.Rect; import android.os.Handler; import android.os.IBinder; import android.util.Log; +import android.view.DragEvent; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.MotionEvent; @@ -73,8 +74,10 @@ public class DragController { private final int[] mCoordinatesTemp = new int[2]; private final boolean mIsRtl; - /** Whether or not we're dragging. */ - private boolean mDragging; + /** + * Drag driver for the current drag/drop operation, or null if there is no active DND operation. + */ + private DragDriver mDragDriver = null; /** Whether or not this is an accessible drag operation */ private boolean mIsAccessibleDrag; @@ -161,10 +164,6 @@ public class DragController { mIsRtl = Utilities.isRtl(r); } - public boolean dragging() { - return mDragging; - } - /** * Starts a drag. * @@ -234,8 +233,8 @@ public class DragController { final int dragRegionLeft = dragRegion == null ? 0 : dragRegion.left; final int dragRegionTop = dragRegion == null ? 0 : dragRegion.top; - mDragging = true; mIsAccessibleDrag = accessible; + mLastDropTarget = null; mDragObject = new DropTarget.DragObject(); @@ -256,6 +255,8 @@ public class DragController { final DragView dragView = mDragObject.dragView = new DragView(mLauncher, b, registrationX, registrationY, 0, 0, b.getWidth(), b.getHeight(), initialDragViewScale); + mDragDriver = DragDriver.create(this, dragInfo, dragView); + if (dragOffset != null) { dragView.setDragVisualizeOffset(new Point(dragOffset)); } @@ -318,18 +319,18 @@ public class DragController { * */ public boolean dispatchKeyEvent(KeyEvent event) { - return mDragging; + return mDragDriver != null; } public boolean isDragging() { - return mDragging; + return mDragDriver != null; } /** * Stop dragging without dropping. */ public void cancelDrag() { - if (mDragging) { + if (mDragDriver != null) { if (mLastDropTarget != null) { mLastDropTarget.onDragExit(mDragObject); } @@ -363,8 +364,8 @@ public class DragController { } private void endDrag() { - if (mDragging) { - mDragging = false; + if (mDragDriver != null) { + mDragDriver = null; mIsAccessibleDrag = false; clearScrollRunnable(); boolean isDeferred = false; @@ -416,7 +417,7 @@ public class DragController { } long getLastGestureUpTime() { - if (mDragging) { + if (mDragDriver != null) { return System.currentTimeMillis(); } else { return mLastTouchUpTime; @@ -427,6 +428,45 @@ public class DragController { mLastTouchUpTime = -1; } + /** + * Call this from the drag driver. + */ + public void onDriverDragMove(float x, float y) { + final int[] dragLayerPos = getClampedDragLayerPos(x, y); + + handleMoveEvent(dragLayerPos[0], dragLayerPos[1]); + } + + /** + * Call this from the drag driver. + */ + public void onDriverDragEnd(float x, float y, DropTarget dropTargetOverride) { + final int[] dragLayerPos = getClampedDragLayerPos(x, y); + final int dragLayerX = dragLayerPos[0]; + final int dragLayerY = dragLayerPos[1]; + + DropTarget dropTarget; + PointF vec = null; + + if (dropTargetOverride != null) { + dropTarget = dropTargetOverride; + } else { + vec = isFlingingToDelete(mDragObject.dragSource); + if (!DeleteDropTarget.supportsDrop(mDragObject.dragInfo)) { + vec = null; + } + if (vec != null) { + dropTarget = mFlingToDeleteDropTarget; + } else { + dropTarget = findDropTarget((int) x, (int) y, mCoordinatesTemp); + } + } + + drop(dropTarget, x, y, vec); + + endDrag(); + } + /** * Call this from a drag source view. */ @@ -434,8 +474,8 @@ public class DragController { @SuppressWarnings("all") // suppress dead code warning final boolean debug = false; if (debug) { - Log.d(Launcher.TAG, "DragController.onInterceptTouchEvent " + ev + " mDragging=" - + mDragging); + Log.d(Launcher.TAG, "DragController.onInterceptTouchEvent " + ev + " Dragging=" + + (mDragDriver != null)); } if (mIsAccessibleDrag) { @@ -451,35 +491,33 @@ public class DragController { final int dragLayerY = dragLayerPos[1]; switch (action) { - case MotionEvent.ACTION_MOVE: - break; case MotionEvent.ACTION_DOWN: // Remember location of down touch mMotionDownX = dragLayerX; mMotionDownY = dragLayerY; - mLastDropTarget = null; break; case MotionEvent.ACTION_UP: mLastTouchUpTime = System.currentTimeMillis(); - if (mDragging) { - PointF vec = isFlingingToDelete(mDragObject.dragSource); - if (!DeleteDropTarget.supportsDrop(mDragObject.dragInfo)) { - vec = null; - } - if (vec != null) { - dropOnFlingToDeleteTarget(dragLayerX, dragLayerY, vec); - } else { - drop(dragLayerX, dragLayerY); - } - } - endDrag(); - break; - case MotionEvent.ACTION_CANCEL: - cancelDrag(); break; } - return mDragging; + return mDragDriver != null && mDragDriver.onInterceptTouchEvent(ev); + } + + /** + * Call this from a drag source view. + */ + public boolean onDragEvent(DragEvent event) { + return mDragDriver != null && mDragDriver.onDragEvent(event); + } + + /** + * Call this from a drag view. + */ + public void onDragViewAnimationEnd() { + if (mDragDriver != null ) { + mDragDriver.onDragViewAnimationEnd(); + } } /** @@ -579,7 +617,7 @@ public class DragController { * Call this from a drag source view. */ public boolean onTouchEvent(MotionEvent ev) { - if (!mDragging || mIsAccessibleDrag) { + if (mDragDriver == null || mIsAccessibleDrag) { return false; } @@ -592,47 +630,25 @@ public class DragController { final int dragLayerY = dragLayerPos[1]; switch (action) { - case MotionEvent.ACTION_DOWN: - // Remember where the motion event started - mMotionDownX = dragLayerX; - mMotionDownY = dragLayerY; + 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; - } - handleMoveEvent(dragLayerX, dragLayerY); - 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) { - PointF vec = isFlingingToDelete(mDragObject.dragSource); - if (!DeleteDropTarget.supportsDrop(mDragObject.dragInfo)) { - vec = null; - } - if (vec != null) { - dropOnFlingToDeleteTarget(dragLayerX, dragLayerY, vec); + if ((dragLayerX < mScrollZone) || (dragLayerX > mScrollView.getWidth() - mScrollZone)) { + mScrollState = SCROLL_WAITING_IN_ZONE; + mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY); } else { - drop(dragLayerX, dragLayerY); + mScrollState = SCROLL_OUTSIDE_ZONE; } - } - endDrag(); - break; - case MotionEvent.ACTION_CANCEL: - mHandler.removeCallbacks(mScrollRunnable); - cancelDrag(); - break; + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + mHandler.removeCallbacks(mScrollRunnable); + break; } - return true; + return mDragDriver.onTouchEvent(ev); } /** @@ -642,7 +658,6 @@ public class DragController { public void prepareAccessibleDrag(int x, int y) { mMotionDownX = x; mMotionDownY = y; - mLastDropTarget = null; } /** @@ -660,7 +675,7 @@ public class DragController { dropTarget.prepareAccessibilityDrop(); // Perform the drop - drop(location[0], location[1]); + drop(dropTarget, location[0], location[1], null); endDrag(); } @@ -690,49 +705,41 @@ public class DragController { return null; } - private void dropOnFlingToDeleteTarget(float x, float y, PointF vel) { + void drop(DropTarget dropTarget, float x, float y, PointF flingVel) { final int[] coordinates = mCoordinatesTemp; mDragObject.x = coordinates[0]; mDragObject.y = coordinates[1]; - // Clean up dragging on the target if it's not the current fling delete target otherwise, - // start dragging to it. - if (mLastDropTarget != null && mFlingToDeleteDropTarget != mLastDropTarget) { - mLastDropTarget.onDragExit(mDragObject); + // Move dragging to the final target. + if (dropTarget != mLastDropTarget) { + if (mLastDropTarget != null) { + mLastDropTarget.onDragExit(mDragObject); + } + mLastDropTarget = dropTarget; + if (dropTarget != null) { + dropTarget.onDragEnter(mDragObject); + } } - // Drop onto the fling-to-delete target - boolean accepted = false; - mFlingToDeleteDropTarget.onDragEnter(mDragObject); - // We must set dragComplete to true _only_ after we "enter" the fling-to-delete target for - // "drop" mDragObject.dragComplete = true; - mFlingToDeleteDropTarget.onDragExit(mDragObject); - if (mFlingToDeleteDropTarget.acceptDrop(mDragObject)) { - mFlingToDeleteDropTarget.onFlingToDelete(mDragObject, vel); - accepted = true; - } - mDragObject.dragSource.onDropCompleted((View) mFlingToDeleteDropTarget, mDragObject, true, - accepted); - } - 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]; + // Drop onto the target. boolean accepted = false; if (dropTarget != null) { - mDragObject.dragComplete = true; dropTarget.onDragExit(mDragObject); if (dropTarget.acceptDrop(mDragObject)) { - dropTarget.onDrop(mDragObject); + if (flingVel != null) { + dropTarget.onFlingToDelete(mDragObject, flingVel); + } else { + dropTarget.onDrop(mDragObject); + } accepted = true; } } - mDragObject.dragSource.onDropCompleted((View) dropTarget, mDragObject, false, accepted); + final View dropTargetAsView = dropTarget instanceof View ? (View) dropTarget : null; + mDragObject.dragSource.onDropCompleted( + dropTargetAsView, mDragObject, flingVel != null, accepted); } private DropTarget findDropTarget(int x, int y, int[] dropCoordinates) { diff --git a/src/com/android/launcher3/DragDriver.java b/src/com/android/launcher3/DragDriver.java new file mode 100644 index 0000000000..56b76329c7 --- /dev/null +++ b/src/com/android/launcher3/DragDriver.java @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3; + +import android.content.ClipData; +import android.content.Intent; +import android.graphics.Canvas; +import android.graphics.Point; +import android.view.DragEvent; +import android.view.MotionEvent; +import android.view.View; + +/** + * Base class for driving a drag/drop operation. + */ +public abstract class DragDriver { + protected final DragController mDragController; + + public DragDriver(DragController dragController) { + mDragController = dragController; + } + + /** + * Handles ending of the DragView animation. + */ + public abstract void onDragViewAnimationEnd(); + + public abstract boolean onTouchEvent(MotionEvent ev); + + public abstract boolean onDragEvent (DragEvent event); + + public abstract boolean onInterceptTouchEvent(MotionEvent ev); + + public static DragDriver create( + DragController dragController, ItemInfo dragInfo, DragView dragView) { + // TODO: Replace the hardcoded constant with looking at the API version. + final boolean useSystemDrag = false; + + if (useSystemDrag) { + return new SystemDragDriver(dragController, dragInfo.getIntent(), dragView); + } else { + return new InternalDragDriver(dragController); + } + } + +}; + +/** + * Class for driving a system (i.e. framework) drag/drop operation. + */ +class SystemDragDriver extends DragDriver { + /** Intent associated with the drag operation, or null is there no associated intent. */ + private final Intent mDragIntent; + + private final DragView mDragView; + boolean mDragging = false; + boolean mReceivedDropEvent = false; + float mLastX = 0; + float mLastY = 0; + + public SystemDragDriver(DragController dragController, Intent dragIntent, DragView dragView) { + super(dragController); + mDragIntent = dragIntent; + mDragView = dragView; + } + + private static class ShadowBuilder extends View.DragShadowBuilder { + final DragView mDragView; + + public ShadowBuilder(DragView dragView) { + mDragView = dragView; + } + + @Override + public void onProvideShadowMetrics (Point size, Point touch) { + mDragView.provideDragShadowMetrics(size, touch); + } + + @Override + public void onDrawShadow(Canvas canvas) { + mDragView.drawDragShadow(canvas); + } + }; + + @Override + public void onDragViewAnimationEnd() { + // Clip data for the drag operation. If there is an intent, create an intent-based ClipData, + // which will be passed to a global DND. + // If there is no intent, craft a fake ClipData and start a local DND operation; this + // ClipData will be ignored. + final ClipData dragData = mDragIntent != null ? + ClipData.newIntent("", mDragIntent) : + ClipData.newPlainText("", ""); + + View.DragShadowBuilder shadowBuilder = new ShadowBuilder(mDragView); + // TODO: DND flags are in flux, once settled, use the appropriate constant. + final int flags = mDragIntent != null ? 1 : 0; + + mDragging = true; + + if (!mDragView.startDrag(dragData, shadowBuilder, null, flags)) { + mDragging = false; + mDragController.cancelDrag(); + return; + } + + // Starting from this point, the driver takes over showing the drag shadow, so hiding the + // drag view. + mDragView.setVisibility(View.INVISIBLE); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + return false; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + return false; + } + + @Override + public boolean onDragEvent (DragEvent event) { + if (!mDragging) { + // We are interested only in drag events started by this driver. + return false; + } + + final int action = event.getAction(); + + switch (action) { + case DragEvent.ACTION_DRAG_STARTED: + return true; + + case DragEvent.ACTION_DRAG_ENTERED: + return true; + + case DragEvent.ACTION_DRAG_LOCATION: + mLastX = event.getX(); + mLastY = event.getY(); + mDragController.onDriverDragMove(event.getX(), event.getY()); + return true; + + case DragEvent.ACTION_DROP: + mReceivedDropEvent = true; + return true; + + case DragEvent.ACTION_DRAG_EXITED: + return true; + + case DragEvent.ACTION_DRAG_ENDED: + final boolean dragAccepted = event.getResult(); + final boolean acceptedByAnotherWindow = dragAccepted && !mReceivedDropEvent; + + // When the system drag ends, its drag shadow disappears. Resume showing the drag + // view for the possible final animation. + mDragView.setVisibility(View.VISIBLE); + + final DropTarget dropTargetOverride = acceptedByAnotherWindow ? + new AnotherWindowDropTarget(mDragView.getContext()) : null; + + mDragController.onDriverDragEnd(mLastX, mLastY, dropTargetOverride); + mDragging = false; + return true; + + default: + return false; + } + } +}; + +/** + * Class for driving an internal (i.e. not using framework) drag/drop operation. + */ +class InternalDragDriver extends DragDriver { + public InternalDragDriver(DragController dragController) { + super(dragController); + } + + @Override + public void onDragViewAnimationEnd() {} + + @Override + public boolean onTouchEvent(MotionEvent ev) { + final int action = ev.getAction(); + + switch (action) { + case MotionEvent.ACTION_MOVE: + mDragController.onDriverDragMove(ev.getX(), ev.getY()); + break; + case MotionEvent.ACTION_UP: + mDragController.onDriverDragMove(ev.getX(), ev.getY()); + mDragController.onDriverDragEnd(ev.getX(), ev.getY(), null); + break; + case MotionEvent.ACTION_CANCEL: + mDragController.cancelDrag(); + break; + } + + return true; + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + final int action = ev.getAction(); + + switch (action) { + case MotionEvent.ACTION_UP: + mDragController.onDriverDragEnd(ev.getX(), ev.getY(), null); + break; + case MotionEvent.ACTION_CANCEL: + mDragController.cancelDrag(); + break; + } + + return true; + } + + @Override + public boolean onDragEvent (DragEvent event) { return false; } +}; diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java index aaa14e6a6c..8445cca3c9 100644 --- a/src/com/android/launcher3/DragLayer.java +++ b/src/com/android/launcher3/DragLayer.java @@ -28,6 +28,7 @@ import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; +import android.view.DragEvent; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -375,6 +376,11 @@ public class DragLayer extends InsettableFrameLayout { return mDragController.onTouchEvent(ev); } + @Override + public boolean onDragEvent (DragEvent event) { + return mDragController.onDragEvent(event); + } + /** * Determine the rect of the descendant in this DragLayer's coordinates * @@ -764,7 +770,7 @@ public class DragLayer extends InsettableFrameLayout { // Show the drop view if it was previously hidden mDropView = view; mDropView.cancelAnimation(); - mDropView.resetLayoutParams(); + mDropView.requestLayout(); // Set the anchor view if the page is scrolling if (anchorView != null) { diff --git a/src/com/android/launcher3/DragView.java b/src/com/android/launcher3/DragView.java index dfa8202a73..10809b55e3 100644 --- a/src/com/android/launcher3/DragView.java +++ b/src/com/android/launcher3/DragView.java @@ -16,6 +16,8 @@ package com.android.launcher3; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.FloatArrayEvaluator; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; @@ -45,18 +47,17 @@ public class DragView extends View { private Bitmap mBitmap; private Bitmap mCrossFadeBitmap; @Thunk Paint mPaint; - private int mRegistrationX; - private int mRegistrationY; + private final int mRegistrationX; + private final int mRegistrationY; private Point mDragVisualizeOffset = null; private Rect mDragRegion = null; - private DragLayer mDragLayer = null; + private final DragLayer mDragLayer; + private final DragController mDragController; private boolean mHasDrawn = false; @Thunk float mCrossFadeProgress = 0f; ValueAnimator mAnim; - @Thunk float mOffsetX = 0.0f; - @Thunk float mOffsetY = 0.0f; private float mInitialScale = 1f; // The intrinsic icon scale factor is the scale factor for a drag icon over the workspace // size. This is ignored for non-icons. @@ -81,6 +82,7 @@ public class DragView extends View { int left, int top, int width, int height, final float initialScale) { super(launcher); mDragLayer = launcher.getDragLayer(); + mDragController = launcher.getDragController(); mInitialScale = initialScale; final Resources res = getResources(); @@ -99,11 +101,6 @@ public class DragView extends View { public void onAnimationUpdate(ValueAnimator animation) { final float value = (Float) animation.getAnimatedValue(); - final int deltaX = (int) (-mOffsetX); - final int deltaY = (int) (-mOffsetY); - - mOffsetX += deltaX; - mOffsetY += deltaY; setScaleX(initialScale + (value * (scale - initialScale))); setScaleY(initialScale + (value * (scale - initialScale))); if (sDragAlpha != 1f) { @@ -112,13 +109,17 @@ public class DragView extends View { if (getParent() == null) { animation.cancel(); - } else { - setTranslationX(getTranslationX() + deltaX); - setTranslationY(getTranslationY() + deltaY); } } }); + mAnim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mDragController.onDragViewAnimationEnd(); + } + }); + mBitmap = Bitmap.createBitmap(bitmap, left, top, width, height); setDragRegion(new Rect(0, 0, width, height)); @@ -145,10 +146,6 @@ public class DragView extends View { return mIntrinsicIconScale; } - public float getOffsetY() { - return mOffsetY; - } - public int getDragRegionLeft() { return mDragRegion.left; } @@ -181,10 +178,6 @@ public class DragView extends View { return mDragRegion; } - public float getInitialScale() { - return mInitialScale; - } - public void updateInitialScaleToCurrentScale() { mInitialScale = getScaleX(); } @@ -194,6 +187,23 @@ public class DragView extends View { setMeasuredDimension(mBitmap.getWidth(), mBitmap.getHeight()); } + // Draws drag shadow for system DND. + public void drawDragShadow(Canvas canvas) { + final int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); + canvas.scale(getScaleX(), getScaleY()); + onDraw(canvas); + canvas.restoreToCount(saveCount); + } + + // Provides drag shadow metrics for system DND. + public void provideDragShadowMetrics(Point size, Point touch) { + size.set((int)(mBitmap.getWidth() * getScaleX()), (int)(mBitmap.getHeight() * getScaleY())); + + final int xGrowth = (int)(mBitmap.getWidth() * (getScaleX() - mInitialScale)); + final int yGrowth = (int)(mBitmap.getHeight() * (getScaleY() - mInitialScale)); + touch.set(mRegistrationX + xGrowth / 2, mRegistrationY + yGrowth / 2); + } + @Override protected void onDraw(Canvas canvas) { @SuppressWarnings("all") // suppress dead code warning @@ -214,12 +224,12 @@ public class DragView extends View { canvas.drawBitmap(mBitmap, 0.0f, 0.0f, mPaint); if (crossFade) { mPaint.setAlpha((int) (255 * mCrossFadeProgress)); - canvas.save(); + final int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); float sX = (mBitmap.getWidth() * 1.0f) / mCrossFadeBitmap.getWidth(); float sY = (mBitmap.getHeight() * 1.0f) / mCrossFadeBitmap.getHeight(); canvas.scale(sX, sY); canvas.drawBitmap(mCrossFadeBitmap, 0.0f, 0.0f, mPaint); - canvas.restore(); + canvas.restoreToCount(saveCount); } } @@ -333,11 +343,6 @@ public class DragView extends View { } } - public void resetLayoutParams() { - mOffsetX = mOffsetY = 0; - requestLayout(); - } - /** * Move the window containing this view. * @@ -345,8 +350,8 @@ public class DragView extends View { * @param touchY the y coordinate the user touched in DragLayer coordinates */ void move(int touchX, int touchY) { - setTranslationX(touchX - mRegistrationX + (int) mOffsetX); - setTranslationY(touchY - mRegistrationY + (int) mOffsetY); + setTranslationX(touchX - mRegistrationX); + setTranslationY(touchY - mRegistrationY); } void remove() { diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java index 4bc501987e..956bb8c759 100644 --- a/src/com/android/launcher3/ItemInfo.java +++ b/src/com/android/launcher3/ItemInfo.java @@ -134,7 +134,7 @@ public class ItemInfo { } public Intent getIntent() { - throw new RuntimeException("Unexpected Intent"); + return null; } /**