Move drop anim into the Workspace to prevent clipping issues
This commit is contained in:
@@ -25,6 +25,9 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.animation.ValueAnimator.AnimatorUpdateListener;
|
||||
import android.app.WallpaperManager;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
@@ -53,6 +56,7 @@ import android.util.Log;
|
||||
import android.view.DragEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
@@ -151,6 +155,11 @@ public class Workspace extends SmoothPagedView
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final int[] mTempXY = new int[2];
|
||||
|
||||
private ValueAnimator mDropAnim = null;
|
||||
private TimeInterpolator mQuintEaseOutInterpolator = new DecelerateInterpolator(2.5f);
|
||||
private View mDropView = null;
|
||||
private int[] mDropViewPos = new int[] { -1, -1 };
|
||||
|
||||
// Paint used to draw external drop outline
|
||||
private final Paint mExternalDragOutlinePaint = new Paint();
|
||||
|
||||
@@ -204,6 +213,7 @@ public class Workspace extends SmoothPagedView
|
||||
LauncherApplication app = (LauncherApplication)context.getApplicationContext();
|
||||
mIconCache = app.getIconCache();
|
||||
mExternalDragOutlinePaint.setAntiAlias(true);
|
||||
setWillNotDraw(false);
|
||||
|
||||
mUnshrinkAnimationListener = new AnimatorListenerAdapter() {
|
||||
public void onAnimationStart(Animator animation) {
|
||||
@@ -579,6 +589,15 @@ public class Workspace extends SmoothPagedView
|
||||
}
|
||||
} else {
|
||||
super.dispatchDraw(canvas);
|
||||
|
||||
if (mDropView != null) {
|
||||
canvas.save(Canvas.MATRIX_SAVE_FLAG);
|
||||
final int xPos = mDropViewPos[0] - mDropView.getScrollX();
|
||||
final int yPos = mDropViewPos[1] - mDropView.getScrollY();
|
||||
canvas.translate(xPos, yPos);
|
||||
mDropView.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1052,6 +1071,7 @@ public class Workspace extends SmoothPagedView
|
||||
CellLayout current = getCurrentDropLayout();
|
||||
|
||||
current.onDragChild(child);
|
||||
child.setVisibility(View.GONE);
|
||||
|
||||
child.clearFocus();
|
||||
child.setPressed(false);
|
||||
@@ -1100,28 +1120,106 @@ public class Workspace extends SmoothPagedView
|
||||
viewX -= getResources().getInteger(R.integer.config_dragViewOffsetX);
|
||||
viewY -= getResources().getInteger(R.integer.config_dragViewOffsetY);
|
||||
|
||||
// Set its old pos (in the new parent's coordinates); the CellLayout will
|
||||
// animate it from this position during the next layout pass
|
||||
// Set its old pos (in the new parent's coordinates); it will be animated
|
||||
// in animateViewIntoPosition after the next layout pass
|
||||
lp.oldX = viewX - (parent.getLeft() - mScrollX);
|
||||
lp.oldY = viewY - (parent.getTop() - mScrollY);
|
||||
}
|
||||
|
||||
public void animateViewIntoPosition(final View view) {
|
||||
final CellLayout parent = (CellLayout) view.getParent();
|
||||
final CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams();
|
||||
|
||||
mDropView = view;
|
||||
|
||||
// Convert the animation params to be relative to the Workspace, not the CellLayout
|
||||
final int fromX = lp.oldX + parent.getLeft();
|
||||
final int fromY = lp.oldY + parent.getTop();
|
||||
|
||||
final int dx = lp.x - lp.oldX;
|
||||
final int dy = lp.y - lp.oldY;
|
||||
|
||||
// Calculate the duration of the animation based on the object's distance
|
||||
final float dist = (float) Math.sqrt(dx*dx + dy*dy);
|
||||
final Resources res = getResources();
|
||||
final float maxDist = (float) res.getInteger(R.integer.config_dropAnimMaxDist);
|
||||
final int duration = (int) (res.getInteger(R.integer.config_dropAnimMaxDuration)
|
||||
* mQuintEaseOutInterpolator.getInterpolation(dist / maxDist));
|
||||
|
||||
// Lazy initialize the animation
|
||||
if (mDropAnim == null) {
|
||||
mDropAnim = new ValueAnimator();
|
||||
mDropAnim.setInterpolator(mQuintEaseOutInterpolator);
|
||||
|
||||
// Make the view invisible during the animation; we'll render it manually.
|
||||
mDropAnim.addListener(new AnimatorListenerAdapter() {
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mDropView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (mDropView != null) {
|
||||
mDropView.setVisibility(View.VISIBLE);
|
||||
mDropView = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mDropAnim.end(); // Make sure it's not already running
|
||||
}
|
||||
mDropAnim.setDuration(duration);
|
||||
mDropAnim.setFloatValues(0.0f, 1.0f);
|
||||
mDropAnim.removeAllUpdateListeners();
|
||||
mDropAnim.addUpdateListener(new AnimatorUpdateListener() {
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
final float percent = (Float) animation.getAnimatedValue();
|
||||
// Invalidate the old position
|
||||
invalidate(mDropViewPos[0], mDropViewPos[1],
|
||||
mDropViewPos[0] + view.getWidth(), mDropViewPos[1] + view.getHeight());
|
||||
|
||||
mDropViewPos[0] = fromX + (int) (percent * dx + 0.5f);
|
||||
mDropViewPos[1] = fromY + (int) (percent * dy + 0.5f);
|
||||
invalidate(mDropViewPos[0], mDropViewPos[1],
|
||||
mDropViewPos[0] + view.getWidth(), mDropViewPos[1] + view.getHeight());
|
||||
}
|
||||
});
|
||||
mDropAnim.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean acceptDrop(DragSource source, int x, int y,
|
||||
int xOffset, int yOffset, DragView dragView, Object dragInfo) {
|
||||
|
||||
// If it's an external drop (e.g. from All Apps), check if it should be accepted
|
||||
if (source != this) {
|
||||
// Don't accept the drop if we're not over a screen at time of drop
|
||||
if (mDragTargetLayout == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final CellLayout.CellInfo dragCellInfo = mDragInfo;
|
||||
final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX;
|
||||
final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY;
|
||||
|
||||
final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell;
|
||||
|
||||
// Don't accept the drop if there's no room for the item
|
||||
if (!mDragTargetLayout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
|
||||
mLauncher.showOutOfSpaceMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onDrop(DragSource source, int x, int y, int xOffset, int yOffset,
|
||||
DragView dragView, Object dragInfo) {
|
||||
|
||||
int originX = x - xOffset;
|
||||
int originY = y - yOffset;
|
||||
|
||||
if (mDragTargetLayout == null) {
|
||||
// Cancel the drag if we're not over a screen at time of drop
|
||||
if (mDragInfo != null) {
|
||||
// Set its position so the parent can animate it back
|
||||
final View parent = getChildAt(mDragInfo.screen);
|
||||
setPositionForDropAnimation(dragView, originX, originY, parent, mDragInfo.cell);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (mIsSmall || mIsInUnshrinkAnimation) {
|
||||
// get originX and originY in the local coordinate system of the screen
|
||||
mTempOriginXY[0] = originX;
|
||||
@@ -1134,37 +1232,41 @@ public class Workspace extends SmoothPagedView
|
||||
if (source != this) {
|
||||
onDropExternal(originX, originY, dragInfo, mDragTargetLayout);
|
||||
} else if (mDragInfo != null) {
|
||||
// Move internally
|
||||
final View cell = mDragInfo.cell;
|
||||
mTargetCell = findNearestVacantArea(originX, originY,
|
||||
mDragInfo.spanX, mDragInfo.spanY, cell, mDragTargetLayout,
|
||||
mTargetCell);
|
||||
if (mDragTargetLayout != null) {
|
||||
// Move internally
|
||||
mTargetCell = findNearestVacantArea(originX, originY,
|
||||
mDragInfo.spanX, mDragInfo.spanY, cell, mDragTargetLayout,
|
||||
mTargetCell);
|
||||
|
||||
int screen = indexOfChild(mDragTargetLayout);
|
||||
if (screen != mDragInfo.screen) {
|
||||
final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
|
||||
originalCellLayout.removeView(cell);
|
||||
addInScreen(cell, screen, mTargetCell[0], mTargetCell[1],
|
||||
mDragInfo.spanX, mDragInfo.spanY);
|
||||
int screen = indexOfChild(mDragTargetLayout);
|
||||
if (screen != mDragInfo.screen) {
|
||||
final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen);
|
||||
originalCellLayout.removeView(cell);
|
||||
addInScreen(cell, 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();
|
||||
mDragTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
|
||||
lp.cellX = mTargetCell[0];
|
||||
lp.cellY = mTargetCell[1];
|
||||
cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
|
||||
mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
|
||||
|
||||
LauncherModel.moveItemInDatabase(mLauncher, info,
|
||||
LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
|
||||
lp.cellX, lp.cellY);
|
||||
}
|
||||
mDragTargetLayout.onDropChild(cell);
|
||||
|
||||
// update the item's position after drop
|
||||
final ItemInfo info = (ItemInfo) cell.getTag();
|
||||
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
|
||||
mDragTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
|
||||
lp.cellX = mTargetCell[0];
|
||||
lp.cellY = mTargetCell[1];
|
||||
cell.setId(LauncherModel.getCellLayoutChildId(-1, mDragInfo.screen,
|
||||
mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
|
||||
|
||||
LauncherModel.moveItemInDatabase(mLauncher, info,
|
||||
LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
|
||||
lp.cellX, lp.cellY);
|
||||
final CellLayout parent = (CellLayout) cell.getParent();
|
||||
|
||||
// Prepare it to be animated into its new position
|
||||
// This must be called after the view has been re-parented
|
||||
setPositionForDropAnimation(dragView, originX, originY, mDragTargetLayout, cell);
|
||||
setPositionForDropAnimation(dragView, originX, originY, parent, cell);
|
||||
parent.onDropChild(cell);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1669,30 +1771,6 @@ public class Workspace extends SmoothPagedView
|
||||
return mDragInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public boolean acceptDrop(DragSource source, int x, int y,
|
||||
int xOffset, int yOffset, DragView dragView, Object dragInfo) {
|
||||
if (mDragTargetLayout == null) {
|
||||
// cancel the drag if we're not over a screen at time of drop
|
||||
return false;
|
||||
}
|
||||
|
||||
final CellLayout.CellInfo dragCellInfo = mDragInfo;
|
||||
final int spanX = dragCellInfo == null ? 1 : dragCellInfo.spanX;
|
||||
final int spanY = dragCellInfo == null ? 1 : dragCellInfo.spanY;
|
||||
|
||||
final View ignoreView = dragCellInfo == null ? null : dragCellInfo.cell;
|
||||
|
||||
if (mDragTargetLayout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
|
||||
return true;
|
||||
} else {
|
||||
mLauncher.showOutOfSpaceMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the nearest cell where the given object would be dropped.
|
||||
*/
|
||||
@@ -1733,7 +1811,7 @@ public class Workspace extends SmoothPagedView
|
||||
// final Object tag = mDragInfo.cell.getTag();
|
||||
}
|
||||
} else if (mDragInfo != null) {
|
||||
((CellLayout) getChildAt(mDragInfo.screen)).onDropAborted(mDragInfo.cell);
|
||||
((CellLayout) getChildAt(mDragInfo.screen)).onDropChild(mDragInfo.cell);
|
||||
}
|
||||
|
||||
mDragOutline = null;
|
||||
|
||||
Reference in New Issue
Block a user