Code to enable dragging to System UI shelf.

This CL doesn’t let the new code run, it’s under a compile-time flag,
and the behavior should be same as before.

The change introduces a concept of a DragDriver, which encapsulates
behavior of the existing DND (InternalDragDriver) or the framework-
driven DND (SystemDragDriver).

An instance of DragDriver gets created by DragController for the time
while a DND operation is in progress, and it takes care of translating
DND events for DragController.

Also did some cleanups, like removing meaningless fields etc.

Plans for future: keep working in Burnaby, and:
* Perhaps, better separate DragDriver from DragController
* Detect fling gesture for system DND
* Look at accessibility
* Polish animations and appearance
* Fix dragging from folders
* Support cancelling DND

Then, it will become possible to enable new dragging (based on Android
version).

Bug: 22028725
Change-Id: I41b40e9d512d83937f5b101ac8e3e8e7e807c269
This commit is contained in:
Vadim Tryshev
2015-07-08 13:40:14 -07:00
parent 1992d126f4
commit d6c8e7eeb1
6 changed files with 458 additions and 132 deletions
@@ -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; }
}
+107 -100
View File
@@ -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 {
* </pre>
*/
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) {
+235
View File
@@ -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; }
};
+7 -1
View File
@@ -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) {
+35 -30
View File
@@ -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() {
+1 -1
View File
@@ -134,7 +134,7 @@ public class ItemInfo {
}
public Intent getIntent() {
throw new RuntimeException("Unexpected Intent");
return null;
}
/**