summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/launcher2/AppWidgetResizeFrame.java2
-rw-r--r--src/com/android/launcher2/AppsCustomizePagedView.java3
-rw-r--r--src/com/android/launcher2/CellLayout.java207
-rw-r--r--src/com/android/launcher2/DragLayer.java21
-rw-r--r--src/com/android/launcher2/InstallWidgetReceiver.java2
-rw-r--r--src/com/android/launcher2/ItemInfo.java9
-rw-r--r--src/com/android/launcher2/Launcher.java36
-rw-r--r--src/com/android/launcher2/PendingAddItemInfo.java6
-rw-r--r--src/com/android/launcher2/Workspace.java284
9 files changed, 425 insertions, 145 deletions
diff --git a/src/com/android/launcher2/AppWidgetResizeFrame.java b/src/com/android/launcher2/AppWidgetResizeFrame.java
index 6d132ebf0..c01a882cb 100644
--- a/src/com/android/launcher2/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher2/AppWidgetResizeFrame.java
@@ -80,7 +80,7 @@ public class AppWidgetResizeFrame extends FrameLayout {
mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
final AppWidgetProviderInfo info = widgetView.getAppWidgetInfo();
- int[] result = mLauncher.getMinResizeSpanForWidget(info, null);
+ int[] result = mLauncher.getMinSpanForWidget(info, null);
mMinHSpan = result[0];
mMinVSpan = result[1];
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index 2001ad929..3fcff726f 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -629,6 +629,9 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
spanXY[1], createWidgetInfo, true);
createItemInfo.spanX = spanXY[0];
createItemInfo.spanY = spanXY[1];
+ int[] minSpanXY = mLauncher.getMinSpanForWidget(createWidgetInfo, null);
+ createWidgetInfo.minSpanX = minSpanXY[0];
+ createWidgetInfo.minSpanY = minSpanXY[1];
FastBitmapDrawable previewDrawable = (FastBitmapDrawable) image.getDrawable();
float minScale = 1.25f;
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 5df271ec9..37328ef2e 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -34,7 +34,6 @@ import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.util.AttributeSet;
@@ -53,6 +52,7 @@ import com.android.launcher2.FolderIcon.FolderRingAnimator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.Stack;
public class CellLayout extends ViewGroup {
static final String TAG = "CellLayout";
@@ -109,7 +109,7 @@ public class CellLayout extends ViewGroup {
// These arrays are used to implement the drag visualization on x-large screens.
// They are used as circular arrays, indexed by mDragOutlineCurrent.
- private Point[] mDragOutlines = new Point[4];
+ private Rect[] mDragOutlines = new Rect[4];
private float[] mDragOutlineAlphas = new float[mDragOutlines.length];
private InterruptibleInOutAnimator[] mDragOutlineAnims =
new InterruptibleInOutAnimator[mDragOutlines.length];
@@ -198,7 +198,7 @@ public class CellLayout extends ViewGroup {
mDragCell[0] = mDragCell[1] = -1;
for (int i = 0; i < mDragOutlines.length; i++) {
- mDragOutlines[i] = new Point(-1, -1);
+ mDragOutlines[i] = new Rect(-1, -1, -1, -1);
}
// When dragging things around the home screens, we show a green outline of
@@ -232,10 +232,7 @@ public class CellLayout extends ViewGroup {
animation.cancel();
} else {
mDragOutlineAlphas[thisIndex] = (Float) animation.getAnimatedValue();
- final int left = mDragOutlines[thisIndex].x;
- final int top = mDragOutlines[thisIndex].y;
- CellLayout.this.invalidate(left, top,
- left + outline.getWidth(), top + outline.getHeight());
+ CellLayout.this.invalidate(mDragOutlines[thisIndex]);
}
}
});
@@ -419,10 +416,10 @@ public class CellLayout extends ViewGroup {
for (int i = 0; i < mDragOutlines.length; i++) {
final float alpha = mDragOutlineAlphas[i];
if (alpha > 0) {
- final Point p = mDragOutlines[i];
+ final Rect r = mDragOutlines[i];
final Bitmap b = (Bitmap) mDragOutlineAnims[i].getTag();
paint.setAlpha((int)(alpha + .5f));
- canvas.drawBitmap(b, p.x, p.y, paint);
+ canvas.drawBitmap(b, null, r, paint);
}
}
@@ -1038,11 +1035,16 @@ public class CellLayout extends ViewGroup {
}
void visualizeDropLocation(View v, Bitmap dragOutline, int originX, int originY,
- int spanX, int spanY, Point dragOffset, Rect dragRegion) {
+ int minSpanX, int minSpanY, int spanX, int spanY, Point dragOffset, Rect dragRegion) {
final int oldDragCellX = mDragCell[0];
final int oldDragCellY = mDragCell[1];
- final int[] nearest = findNearestVacantArea(originX, originY, spanX, spanY, v, mDragCell);
+ int[] resultSpan = new int[2];
+ final int[] nearest = findNearestVacantArea(originX, originY, minSpanX, minSpanY,
+ spanX, spanY, v, mDragCell, resultSpan);
+ boolean resize = spanX > resultSpan[0] || spanY > resultSpan[1];
+ spanX = resultSpan[0];
+ spanY = resultSpan[1];
if (v != null && dragOffset == null) {
mDragCenter.set(originX + (v.getWidth() / 2), originY + (v.getHeight() / 2));
} else {
@@ -1093,12 +1095,15 @@ public class CellLayout extends ViewGroup {
- dragOutline.getHeight()) / 2;
}
}
-
final int oldIndex = mDragOutlineCurrent;
mDragOutlineAnims[oldIndex].animateOut();
mDragOutlineCurrent = (oldIndex + 1) % mDragOutlines.length;
+ Rect r = mDragOutlines[mDragOutlineCurrent];
+ r.set(left, top, left + dragOutline.getWidth(), top + dragOutline.getHeight());
+ if (resize) {
+ cellToRect(nearest[0], nearest[1], spanX, spanY, r);
+ }
- mDragOutlines[mDragOutlineCurrent].set(left, top);
mDragOutlineAnims[mDragOutlineCurrent].setTag(dragOutline);
mDragOutlineAnims[mDragOutlineCurrent].animateIn();
}
@@ -1112,8 +1117,7 @@ public class CellLayout extends ViewGroup {
public void clearDragOutlines() {
final int oldIndex = mDragOutlineCurrent;
mDragOutlineAnims[oldIndex].animateOut();
- mDragCell[0] = -1;
- mDragCell[1] = -1;
+ mDragCell[0] = mDragCell[1] = -1;
}
/**
@@ -1129,8 +1133,8 @@ public class CellLayout extends ViewGroup {
* @return The X, Y cell of a vacant area that can contain this object,
* nearest the requested location.
*/
- int[] findNearestVacantArea(
- int pixelX, int pixelY, int spanX, int spanY, int[] result) {
+ int[] findNearestVacantArea(int pixelX, int pixelY, int spanX, int spanY,
+ int[] result) {
return findNearestVacantArea(pixelX, pixelY, spanX, spanY, null, result);
}
@@ -1140,6 +1144,27 @@ public class CellLayout extends ViewGroup {
*
* @param pixelX The X location at which you want to search for a vacant area.
* @param pixelY The Y location at which you want to search for a vacant area.
+ * @param minSpanX The minimum horizontal span required
+ * @param minSpanY The minimum vertical span required
+ * @param spanX Horizontal span of the object.
+ * @param spanY Vertical span of the object.
+ * @param result Array in which to place the result, or null (in which case a new array will
+ * be allocated)
+ * @return The X, Y cell of a vacant area that can contain this object,
+ * nearest the requested location.
+ */
+ int[] findNearestVacantArea(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX,
+ int spanY, int[] result, int[] resultSpan) {
+ return findNearestVacantArea(pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, null,
+ result, resultSpan);
+ }
+
+ /**
+ * Find a vacant area that will fit the given bounds nearest the requested
+ * cell location. Uses Euclidean distance to score multiple vacant areas.
+ *
+ * @param pixelX The X location at which you want to search for a vacant area.
+ * @param pixelY The Y location at which you want to search for a vacant area.
* @param spanX Horizontal span of the object.
* @param spanY Vertical span of the object.
* @param ignoreOccupied If true, the result can be an occupied cell
@@ -1150,6 +1175,43 @@ public class CellLayout extends ViewGroup {
*/
int[] findNearestArea(int pixelX, int pixelY, int spanX, int spanY, View ignoreView,
boolean ignoreOccupied, int[] result) {
+ return findNearestArea(pixelX, pixelY, spanX, spanY,
+ spanX, spanY, ignoreView, ignoreOccupied, result, null);
+ }
+
+ private final Stack<Rect> mTempRectStack = new Stack<Rect>();
+ private void lazyInitTempRectStack() {
+ if (mTempRectStack.isEmpty()) {
+ for (int i = 0; i < mCountX * mCountY; i++) {
+ mTempRectStack.push(new Rect());
+ }
+ }
+ }
+ private void recycleTempRects(Stack<Rect> used) {
+ while (!used.isEmpty()) {
+ mTempRectStack.push(used.pop());
+ }
+ }
+
+ /**
+ * Find a vacant area that will fit the given bounds nearest the requested
+ * cell location. Uses Euclidean distance to score multiple vacant areas.
+ *
+ * @param pixelX The X location at which you want to search for a vacant area.
+ * @param pixelY The Y location at which you want to search for a vacant area.
+ * @param minSpanX The minimum horizontal span required
+ * @param minSpanY The minimum vertical span required
+ * @param spanX Horizontal span of the object.
+ * @param spanY Vertical span of the object.
+ * @param ignoreOccupied If true, the result can be an occupied cell
+ * @param result Array in which to place the result, or null (in which case a new array will
+ * be allocated)
+ * @return The X, Y cell of a vacant area that can contain this object,
+ * nearest the requested location.
+ */
+ int[] findNearestArea(int pixelX, int pixelY, int minSpanX, int minSpanY, int spanX, int spanY,
+ View ignoreView, boolean ignoreOccupied, int[] result, int[] resultSpan) {
+ lazyInitTempRectStack();
// mark space take by ignoreView as available (method checks if ignoreView is null)
markCellsAsUnoccupiedForView(ignoreView);
@@ -1162,35 +1224,99 @@ public class CellLayout extends ViewGroup {
// Keep track of best-scoring drop area
final int[] bestXY = result != null ? result : new int[2];
double bestDistance = Double.MAX_VALUE;
+ final Rect bestRect = new Rect(-1, -1, -1, -1);
+ final Stack<Rect> validRegions = new Stack<Rect>();
final int countX = mCountX;
final int countY = mCountY;
final boolean[][] occupied = mOccupied;
- for (int y = 0; y < countY - (spanY - 1); y++) {
+ if (minSpanX <= 0 || minSpanY <= 0 || spanX <= 0 || spanY <= 0 ||
+ spanX < minSpanX || spanY < minSpanY) {
+ return bestXY;
+ }
+
+ for (int y = 0; y < countY - (minSpanY - 1); y++) {
inner:
- for (int x = 0; x < countX - (spanX - 1); x++) {
+ for (int x = 0; x < countX - (minSpanX - 1); x++) {
+ int ySize = -1;
+ int xSize = -1;
if (ignoreOccupied) {
- for (int i = 0; i < spanX; i++) {
- for (int j = 0; j < spanY; j++) {
+ // First, let's see if this thing fits anywhere
+ for (int i = 0; i < minSpanX; i++) {
+ for (int j = 0; j < minSpanY; j++) {
if (occupied[x + i][y + j]) {
- // small optimization: we can skip to after the column we
- // just found an occupied cell
- x += i;
continue inner;
}
}
}
+ xSize = minSpanX;
+ ySize = minSpanY;
+
+ // We know that the item will fit at _some_ acceptable size, now let's see
+ // how big we can make it. We'll alternate between incrementing x and y spans
+ // until we hit a limit.
+ boolean incX = true;
+ boolean hitMaxX = xSize >= spanX;
+ boolean hitMaxY = ySize >= spanY;
+ while (!(hitMaxX && hitMaxY)) {
+ if (incX && !hitMaxX) {
+ for (int j = 0; j < ySize; j++) {
+ if (x + xSize > countX -1 || occupied[x + xSize][y + j]) {
+ // We can't move out horizontally
+ hitMaxX = true;
+ }
+ }
+ if (!hitMaxX) {
+ xSize++;
+ }
+ } else if (!hitMaxY) {
+ for (int i = 0; i < xSize; i++) {
+ if (y + ySize > countY - 1 || occupied[x + i][y + ySize]) {
+ // We can't move out vertically
+ hitMaxY = true;
+ }
+ }
+ if (!hitMaxY) {
+ ySize++;
+ }
+ }
+ hitMaxX |= xSize >= spanX;
+ hitMaxY |= ySize >= spanY;
+ incX = !incX;
+ }
+ incX = true;
+ hitMaxX = xSize >= spanX;
+ hitMaxY = ySize >= spanY;
}
final int[] cellXY = mTmpXY;
cellToCenterPoint(x, y, cellXY);
+ // We verify that the current rect is not a sub-rect of any of our previous
+ // candidates. In this case, the current rect is disqualified in favour of the
+ // containing rect.
+ Rect currentRect = mTempRectStack.pop();
+ currentRect.set(x, y, x + xSize, y + ySize);
+ boolean contained = false;
+ for (Rect r : validRegions) {
+ if (r.contains(currentRect)) {
+ contained = true;
+ break;
+ }
+ }
+ validRegions.push(currentRect);
double distance = Math.sqrt(Math.pow(cellXY[0] - pixelX, 2)
+ Math.pow(cellXY[1] - pixelY, 2));
- if (distance <= bestDistance) {
+ if ((distance <= bestDistance && !contained) ||
+ currentRect.contains(bestRect)) {
bestDistance = distance;
bestXY[0] = x;
bestXY[1] = y;
+ if (resultSpan != null) {
+ resultSpan[0] = xSize;
+ resultSpan[1] = ySize;
+ }
+ bestRect.set(currentRect);
}
}
}
@@ -1202,6 +1328,7 @@ public class CellLayout extends ViewGroup {
bestXY[0] = -1;
bestXY[1] = -1;
}
+ recycleTempRects(validRegions);
return bestXY;
}
@@ -1224,6 +1351,27 @@ public class CellLayout extends ViewGroup {
}
/**
+ * Find a vacant area that will fit the given bounds nearest the requested
+ * cell location. Uses Euclidean distance to score multiple vacant areas.
+ *
+ * @param pixelX The X location at which you want to search for a vacant area.
+ * @param pixelY The Y location at which you want to search for a vacant area.
+ * @param minSpanX The minimum horizontal span required
+ * @param minSpanY The minimum vertical span required
+ * @param spanX Horizontal span of the object.
+ * @param spanY Vertical span of the object.
+ * @param ignoreView Considers space occupied by this view as unoccupied
+ * @param result Previously returned value to possibly recycle.
+ * @return The X, Y cell of a vacant area that can contain this object,
+ * nearest the requested location.
+ */
+ int[] findNearestVacantArea(int pixelX, int pixelY, int minSpanX, int minSpanY,
+ int spanX, int spanY, View ignoreView, int[] result, int[] resultSpan) {
+ return findNearestArea(pixelX, pixelY, minSpanX, minSpanY,
+ spanX, spanY, ignoreView, true, result, resultSpan);
+ }
+
+ /**
* Find a starting cell position that will fit the given bounds nearest the requested
* cell location. Uses Euclidean distance to score multiple vacant areas.
*
@@ -1390,8 +1538,7 @@ public class CellLayout extends ViewGroup {
}
// Invalidate the drag data
- mDragCell[0] = -1;
- mDragCell[1] = -1;
+ mDragCell[0] = mDragCell[1] = -1;
mDragOutlineAnims[mDragOutlineCurrent].animateOut();
mDragOutlineCurrent = (mDragOutlineCurrent + 1) % mDragOutlineAnims.length;
@@ -1422,7 +1569,7 @@ public class CellLayout extends ViewGroup {
* @param cellVSpan Height in cells
* @param resultRect Rect into which to put the results
*/
- public void cellToRect(int cellX, int cellY, int cellHSpan, int cellVSpan, RectF resultRect) {
+ public void cellToRect(int cellX, int cellY, int cellHSpan, int cellVSpan, Rect resultRect) {
final int cellWidth = mCellWidth;
final int cellHeight = mCellHeight;
final int widthGap = mWidthGap;
@@ -1597,10 +1744,10 @@ out: for (int i = x; i < x + spanX - 1 && x < xCount; i++) {
}
}
- public void onMove(View view, int newCellX, int newCellY) {
+ public void onMove(View view, int newCellX, int newCellY, int newSpanX, int newSpanY) {
LayoutParams lp = (LayoutParams) view.getLayoutParams();
markCellsAsUnoccupiedForView(view);
- markCellsForView(newCellX, newCellY, lp.cellHSpan, lp.cellVSpan, true);
+ markCellsForView(newCellX, newCellY, newSpanX, newSpanY, true);
}
public void markCellsAsOccupiedForView(View view) {
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index 7bc9bc8b1..a3b389d24 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -458,7 +458,7 @@ public class DragLayer extends FrameLayout {
toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
} else if (child instanceof FolderIcon) {
// Account for holographic blur padding on the drag view
- toY -= HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS / 2;
+ toY -= Workspace.DRAG_BITMAP_PADDING / 2;
// Center in the x coordinate about the target's drawable
toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
} else {
@@ -470,28 +470,19 @@ public class DragLayer extends FrameLayout {
final int fromX = r.left;
final int fromY = r.top;
child.setVisibility(INVISIBLE);
- child.setAlpha(0);
Runnable onCompleteRunnable = new Runnable() {
public void run() {
child.setVisibility(VISIBLE);
- ObjectAnimator oa = ObjectAnimator.ofFloat(child, "alpha", 0f, 1f);
- oa.setDuration(60);
- oa.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(android.animation.Animator animation) {
- if (onFinishAnimationRunnable != null) {
- onFinishAnimationRunnable.run();
- }
- }
- });
- oa.start();
+ if (onFinishAnimationRunnable != null) {
+ onFinishAnimationRunnable.run();
+ }
}
};
animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, scale, scale,
- onCompleteRunnable, ANIMATION_END_FADE_OUT, duration, anchorView);
+ onCompleteRunnable, ANIMATION_END_DISAPPEAR, duration, anchorView);
}
- private void animateViewIntoPosition(final DragView view, final int fromX, final int fromY,
+ public void animateViewIntoPosition(final DragView view, final int fromX, final int fromY,
final int toX, final int toY, float finalAlpha, float initScaleX, float initScaleY,
float finalScaleX, float finalScaleY, Runnable onCompleteRunnable,
int animationEndStyle, int duration, View anchorView) {
diff --git a/src/com/android/launcher2/InstallWidgetReceiver.java b/src/com/android/launcher2/InstallWidgetReceiver.java
index 6b3763ce0..a1e9b1187 100644
--- a/src/com/android/launcher2/InstallWidgetReceiver.java
+++ b/src/com/android/launcher2/InstallWidgetReceiver.java
@@ -189,7 +189,7 @@ public class InstallWidgetReceiver {
final PendingAddWidgetInfo createInfo = new PendingAddWidgetInfo(widgetInfo, mMimeType,
mClipData);
mLauncher.addAppWidgetFromDrop(createInfo, LauncherSettings.Favorites.CONTAINER_DESKTOP,
- mTargetLayoutScreen, null, mTargetLayoutPos);
+ mTargetLayoutScreen, null, null, mTargetLayoutPos);
}
}
}
diff --git a/src/com/android/launcher2/ItemInfo.java b/src/com/android/launcher2/ItemInfo.java
index 8d4662495..11a6c0d00 100644
--- a/src/com/android/launcher2/ItemInfo.java
+++ b/src/com/android/launcher2/ItemInfo.java
@@ -77,6 +77,15 @@ class ItemInfo {
int spanY = 1;
/**
+ * Indicates the minimum X cell span.
+ */
+ int minSpanX = 1;
+
+ /**
+ * Indicates the minimum Y cell span.
+ */
+ int minSpanY = 1;
+ /**
* Indicates whether the item is a gesture.
*/
boolean isGesture = false;
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 83ca6754f..d670463f3 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -584,9 +584,9 @@ public final class Launcher extends Activity
}
};
}
- mWorkspace.animateExternalDrop(mWidgetBeingConfigured, cellLayout,
+ mWorkspace.animateWidgetDrop(mWidgetBeingConfigured, cellLayout,
(DragView) mDragLayer.getAnimatedView(), onCompleteRunnable,
- animationType);
+ animationType, mWidgetBeingConfigured.boundWidget, true);
mWidgetBeingConfigured = null;
}
@@ -959,7 +959,7 @@ public final class Launcher extends Activity
return getSpanForWidget(info.provider, info.minWidth, info.minHeight, spanXY);
}
- int[] getMinResizeSpanForWidget(AppWidgetProviderInfo info, int[] spanXY) {
+ int[] getMinSpanForWidget(AppWidgetProviderInfo info, int[] spanXY) {
return getSpanForWidget(info.provider, info.minResizeWidth, info.minResizeHeight, spanXY);
}
@@ -967,6 +967,11 @@ public final class Launcher extends Activity
return getSpanForWidget(info.componentName, info.minWidth, info.minHeight, spanXY);
}
+ int[] getMinSpanForWidget(PendingAddWidgetInfo info, int[] spanXY) {
+ return getSpanForWidget(info.componentName, info.minResizeWidth,
+ info.minResizeHeight, spanXY);
+ }
+
/**
* Add a widget to the workspace.
*
@@ -982,6 +987,7 @@ public final class Launcher extends Activity
// Calculate the grid spans needed to fit this widget
CellLayout layout = getCellLayout(container, screen);
+ int[] minSpanXY = getMinSpanForWidget(appWidgetInfo, null);
int[] spanXY = getSpanForWidget(appWidgetInfo, null);
// Try finding open space on Launcher screen
@@ -989,18 +995,24 @@ public final class Launcher extends Activity
// if we are placing widgets on a "spring-loaded" screen
int[] cellXY = mTmpAddItemCellCoordinates;
int[] touchXY = mPendingAddInfo.dropPos;
+ int[] finalSpan = new int[2];
boolean foundCellSpan = false;
if (mPendingAddInfo.cellX >= 0 && mPendingAddInfo.cellY >= 0) {
cellXY[0] = mPendingAddInfo.cellX;
cellXY[1] = mPendingAddInfo.cellY;
+ spanXY[0] = mPendingAddInfo.spanX;
+ spanXY[1] = mPendingAddInfo.spanY;
foundCellSpan = true;
} else if (touchXY != null) {
// when dragging and dropping, just find the closest free spot
int[] result = layout.findNearestVacantArea(
- touchXY[0], touchXY[1], spanXY[0], spanXY[1], cellXY);
+ touchXY[0], touchXY[1], minSpanXY[0], minSpanXY[1], spanXY[0],
+ spanXY[1], cellXY, finalSpan);
+ spanXY[0] = finalSpan[0];
+ spanXY[1] = finalSpan[1];
foundCellSpan = (result != null);
} else {
- foundCellSpan = layout.findCellForSpan(cellXY, spanXY[0], spanXY[1]);
+ foundCellSpan = layout.findCellForSpan(cellXY, minSpanXY[0], minSpanXY[1]);
}
if (!foundCellSpan) {
@@ -1021,6 +1033,8 @@ public final class Launcher extends Activity
LauncherAppWidgetInfo launcherInfo = new LauncherAppWidgetInfo(appWidgetId);
launcherInfo.spanX = spanXY[0];
launcherInfo.spanY = spanXY[1];
+ launcherInfo.minSpanX = mPendingAddInfo.minSpanX;
+ launcherInfo.minSpanY = mPendingAddInfo.minSpanY;
LauncherModel.addItemToDatabase(this, launcherInfo,
container, screen, cellXY[0], cellXY[1], false);
@@ -1036,6 +1050,7 @@ public final class Launcher extends Activity
}
launcherInfo.hostView.setTag(launcherInfo);
+ launcherInfo.hostView.setVisibility(View.VISIBLE);
mWorkspace.addInScreen(launcherInfo.hostView, container, screen, cellXY[0], cellXY[1],
launcherInfo.spanX, launcherInfo.spanY, isWorkspaceLocked());
@@ -1465,6 +1480,7 @@ public final class Launcher extends Activity
mPendingAddInfo.screen = -1;
mPendingAddInfo.cellX = mPendingAddInfo.cellY = -1;
mPendingAddInfo.spanX = mPendingAddInfo.spanY = -1;
+ mPendingAddInfo.minSpanX = mPendingAddInfo.minSpanY = -1;
mPendingAddInfo.dropPos = null;
}
@@ -1556,15 +1572,22 @@ public final class Launcher extends Activity
* @param position The location on the screen where it was dropped, optional
*/
void addAppWidgetFromDrop(PendingAddWidgetInfo info, long container, int screen,
- int[] cell, int[] loc) {
+ int[] cell, int[] span, int[] loc) {
resetAddInfo();
mPendingAddInfo.container = info.container = container;
mPendingAddInfo.screen = info.screen = screen;
mPendingAddInfo.dropPos = loc;
+ mPendingAddInfo.minSpanX = info.minSpanX;
+ mPendingAddInfo.minSpanY = info.minSpanY;
+
if (cell != null) {
mPendingAddInfo.cellX = cell[0];
mPendingAddInfo.cellY = cell[1];
}
+ if (span != null) {
+ mPendingAddInfo.spanX = span[0];
+ mPendingAddInfo.spanY = span[1];
+ }
AppWidgetHostView hostView = info.boundWidget;
int appWidgetId;
@@ -1575,7 +1598,6 @@ public final class Launcher extends Activity
AppWidgetManager.getInstance(this).bindAppWidgetId(appWidgetId, info.componentName);
}
addAppWidgetImpl(appWidgetId, info);
-
}
void processShortcut(Intent intent) {
diff --git a/src/com/android/launcher2/PendingAddItemInfo.java b/src/com/android/launcher2/PendingAddItemInfo.java
index 09a8a9ebc..d36e21763 100644
--- a/src/com/android/launcher2/PendingAddItemInfo.java
+++ b/src/com/android/launcher2/PendingAddItemInfo.java
@@ -34,6 +34,8 @@ class PendingAddItemInfo extends ItemInfo {
class PendingAddWidgetInfo extends PendingAddItemInfo {
int minWidth;
int minHeight;
+ int minResizeWidth;
+ int minResizeHeight;
int previewImage;
int icon;
AppWidgetProviderInfo info;
@@ -50,6 +52,8 @@ class PendingAddWidgetInfo extends PendingAddItemInfo {
componentName = i.provider;
minWidth = i.minWidth;
minHeight = i.minHeight;
+ minResizeWidth = i.minResizeWidth;
+ minResizeHeight = i.minResizeHeight;
previewImage = i.previewImage;
icon = i.icon;
if (dataMimeType != null && data != null) {
@@ -62,6 +66,8 @@ class PendingAddWidgetInfo extends PendingAddItemInfo {
public PendingAddWidgetInfo(PendingAddWidgetInfo copy) {
minWidth = copy.minWidth;
minHeight = copy.minHeight;
+ minResizeWidth = copy.minResizeWidth;
+ minResizeHeight = copy.minResizeHeight;
previewImage = copy.previewImage;
icon = copy.icon;
info = copy.info;
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index c9898c8fe..e461a85bc 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -17,6 +17,7 @@
package com.android.launcher2;
import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
@@ -40,7 +41,6 @@ import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
-import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region.Op;
@@ -173,6 +173,7 @@ public class Workspace extends SmoothPagedView
private final Rect mTempRect = new Rect();
private final int[] mTempXY = new int[2];
private float mOverscrollFade = 0;
+ public static final int DRAG_BITMAP_PADDING = 0;
// Paint used to draw external drop outline
private final Paint mExternalDragOutlinePaint = new Paint();
@@ -207,9 +208,11 @@ public class Workspace extends SmoothPagedView
final static float TOUCH_SLOP_DAMPING_FACTOR = 4;
// Relating to the animation of items being dropped externally
- public static final int ANIMATE_INTO_POSITION = 0;
- public static final int COMPLETE_TWO_STAGE_WIDGET_DROP_ANIMATION = 1;
- public static final int CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION = 2;
+ public static final int ANIMATE_INTO_POSITION_AND_DISAPPEAR = 0;
+ public static final int ANIMATE_INTO_POSITION_AND_REMAIN = 1;
+ public static final int ANIMATE_INTO_POSITION_AND_RESIZE = 2;
+ public static final int COMPLETE_TWO_STAGE_WIDGET_DROP_ANIMATION = 3;
+ public static final int CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION = 4;
// Relating to workspace drag fade out
private float mDragFadeOutAlpha;
@@ -325,13 +328,13 @@ public class Workspace extends SmoothPagedView
// estimate the size of a widget with spans hSpan, vSpan. return MAX_VALUE for each
// dimension if unsuccessful
public int[] estimateItemSize(int hSpan, int vSpan,
- PendingAddItemInfo pendingItemInfo, boolean springLoaded) {
+ ItemInfo itemInfo, boolean springLoaded) {
int[] size = new int[2];
if (getChildCount() > 0) {
CellLayout cl = (CellLayout) mLauncher.getWorkspace().getChildAt(0);
- RectF r = estimateItemPosition(cl, pendingItemInfo, 0, 0, hSpan, vSpan);
- size[0] = (int) r.width();
- size[1] = (int) r.height();
+ Rect r = estimateItemPosition(cl, itemInfo, 0, 0, hSpan, vSpan);
+ size[0] = r.width();
+ size[1] = r.height();
if (springLoaded) {
size[0] *= mSpringLoadedShrinkFactor;
size[1] *= mSpringLoadedShrinkFactor;
@@ -343,9 +346,9 @@ public class Workspace extends SmoothPagedView
return size;
}
}
- public RectF estimateItemPosition(CellLayout cl, ItemInfo pendingInfo,
+ public Rect estimateItemPosition(CellLayout cl, ItemInfo pendingInfo,
int hCell, int vCell, int hSpan, int vSpan) {
- RectF r = new RectF();
+ Rect r = new Rect();
cl.cellToRect(hCell, vCell, hSpan, vSpan, r);
return r;
}
@@ -1492,23 +1495,18 @@ public class Workspace extends SmoothPagedView
public void onDragStartedWithItem(View v) {
final Canvas canvas = new Canvas();
- // We need to add extra padding to the bitmap to make room for the glow effect
- final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
-
// The outline is used to visualize where the item will land if dropped
- mDragOutline = createDragOutline(v, canvas, bitmapPadding);
+ mDragOutline = createDragOutline(v, canvas, DRAG_BITMAP_PADDING);
}
public void onDragStartedWithItem(PendingAddItemInfo info, Bitmap b, Paint alphaClipPaint) {
final Canvas canvas = new Canvas();
- // We need to add extra padding to the bitmap to make room for the glow effect
- final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
-
int[] size = estimateItemSize(info.spanX, info.spanY, info, false);
// The outline is used to visualize where the item will land if dropped
- mDragOutline = createDragOutline(b, canvas, bitmapPadding, size[0], size[1], alphaClipPaint);
+ mDragOutline = createDragOutline(b, canvas, DRAG_BITMAP_PADDING, size[0],
+ size[1], alphaClipPaint);
}
// we call this method whenever a drag and drop in Launcher finishes, even if Workspace was
@@ -1912,35 +1910,29 @@ public class Workspace extends SmoothPagedView
}
mDragInfo = cellInfo;
- child.setVisibility(GONE);
+ child.setVisibility(INVISIBLE);
child.clearFocus();
child.setPressed(false);
final Canvas canvas = new Canvas();
- // We need to add extra padding to the bitmap to make room for the glow effect
- final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
-
// The outline is used to visualize where the item will land if dropped
- mDragOutline = createDragOutline(child, canvas, bitmapPadding);
+ mDragOutline = createDragOutline(child, canvas, DRAG_BITMAP_PADDING);
beginDragShared(child, this);
}
public void beginDragShared(View child, DragSource source) {
Resources r = getResources();
- // We need to add extra padding to the bitmap to make room for the glow effect
- final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
-
// The drag bitmap follows the touch point around on the screen
- final Bitmap b = createDragBitmap(child, new Canvas(), bitmapPadding);
+ final Bitmap b = createDragBitmap(child, new Canvas(), DRAG_BITMAP_PADDING);
final int bmpWidth = b.getWidth();
mLauncher.getDragLayer().getLocationInDragLayer(child, mTempXY);
final int dragLayerX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
- int dragLayerY = mTempXY[1] - bitmapPadding / 2;
+ int dragLayerY = mTempXY[1] - DRAG_BITMAP_PADDING / 2;
Point dragVisualizeOffset = null;
Rect dragRect = null;
@@ -1954,7 +1946,8 @@ public class Workspace extends SmoothPagedView
dragLayerY += top;
// Note: The drag region is used to calculate drag layer offsets, but the
// dragVisualizeOffset in addition to the dragRect (the size) to position the outline.
- dragVisualizeOffset = new Point(-bitmapPadding / 2, iconPaddingTop - bitmapPadding / 2);
+ dragVisualizeOffset = new Point(-DRAG_BITMAP_PADDING / 2,
+ iconPaddingTop - DRAG_BITMAP_PADDING / 2);
dragRect = new Rect(left, top, right, bottom);
} else if (child instanceof FolderIcon) {
int previewSize = r.getDimensionPixelSize(R.dimen.folder_preview_size);
@@ -2026,8 +2019,14 @@ public class Workspace extends SmoothPagedView
spanY = dragInfo.spanY;
}
+ int minSpanX = spanX;
+ int minSpanY = spanY;
+ if (d.dragInfo instanceof PendingAddWidgetInfo) {
+ minSpanX = ((PendingAddWidgetInfo) d.dragInfo).minSpanX;
+ minSpanY = ((PendingAddWidgetInfo) d.dragInfo).minSpanY;
+ }
mTargetCell = findNearestArea((int) mDragViewVisualCenter[0],
- (int) mDragViewVisualCenter[1], spanX, spanY, mDragTargetLayout, mTargetCell);
+ (int) mDragViewVisualCenter[1], minSpanX, minSpanY, mDragTargetLayout, mTargetCell);
if (willCreateUserFolder((ItemInfo) d.dragInfo, mDragTargetLayout, mTargetCell, true)) {
return true;
}
@@ -2037,7 +2036,7 @@ public class Workspace extends SmoothPagedView
}
// Don't accept the drop if there's no room for the item
- if (!mDragTargetLayout.findCellForSpanIgnoring(null, spanX, spanY, ignoreView)) {
+ if (!mDragTargetLayout.findCellForSpanIgnoring(null, minSpanX, minSpanY, ignoreView)) {
// Don't show the message if we are dropping on the AllApps button and the hotseat
// is full
if (mTargetCell != null && mLauncher.isHotseatLayout(mDragTargetLayout)) {
@@ -2157,7 +2156,7 @@ public class Workspace extends SmoothPagedView
return false;
}
- public void onDrop(DragObject d) {
+ public void onDrop(final DragObject d) {
mDragViewVisualCenter = getDragViewVisualCenter(d.x, d.y, d.xOffset, d.yOffset, d.dragView,
mDragViewVisualCenter);
@@ -2173,6 +2172,7 @@ public class Workspace extends SmoothPagedView
CellLayout dropTargetLayout = mDragTargetLayout;
int snapScreen = -1;
+ boolean resizeOnDrop = false;
if (d.dragSource != this) {
final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
(int) mDragViewVisualCenter[1] };
@@ -2180,6 +2180,7 @@ public class Workspace extends SmoothPagedView
} else if (mDragInfo != null) {
final View cell = mDragInfo.cell;
+ Runnable resizeRunnable = null;
if (dropTargetLayout != null) {
// Move internally
boolean hasMovedLayouts = (getParentCellLayoutForView(cell) != dropTargetLayout);
@@ -2208,29 +2209,46 @@ public class Workspace extends SmoothPagedView
// Aside from the special case where we're dropping a shortcut onto a shortcut,
// we need to find the nearest cell location that is vacant
+ ItemInfo item = (ItemInfo) d.dragInfo;
+ int minSpanX = item.spanX;
+ int minSpanY = item.spanY;
+ if (item.minSpanX > 0 && item.minSpanY > 0) {
+ minSpanX = item.minSpanX;
+ minSpanY = item.minSpanY;
+ }
+ int[] resultSpan = new int[2];
mTargetCell = findNearestVacantArea((int) mDragViewVisualCenter[0],
- (int) mDragViewVisualCenter[1], mDragInfo.spanX, mDragInfo.spanY, cell,
- dropTargetLayout, mTargetCell);
+ (int) mDragViewVisualCenter[1], minSpanX, minSpanY, mDragInfo.spanX,
+ mDragInfo.spanY, cell, dropTargetLayout, mTargetCell, resultSpan);
+ boolean foundCell = mTargetCell[0] >= 0 && mTargetCell[1] >= 0;
+ if (foundCell && (resultSpan[0] != item.spanX || resultSpan[1] != item.spanY)) {
+ resizeOnDrop = true;
+ item.spanX = resultSpan[0];
+ item.spanY = resultSpan[1];
+ }
if (mCurrentPage != screen && !hasMovedIntoHotseat) {
snapScreen = screen;
snapToPage(screen);
}
- if (mTargetCell[0] >= 0 && mTargetCell[1] >= 0) {
+ if (foundCell) {
+ final ItemInfo info = (ItemInfo) cell.getTag();
if (hasMovedLayouts) {
// Reparent the view
getParentCellLayoutForView(cell).removeView(cell);
addInScreen(cell, container, screen, mTargetCell[0], mTargetCell[1],
- mDragInfo.spanX, mDragInfo.spanY);
+ info.spanX, info.spanY);
}
// update the item's position after drop
- final ItemInfo info = (ItemInfo) cell.getTag();
CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
- dropTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1]);
+ dropTargetLayout.onMove(cell, mTargetCell[0], mTargetCell[1],
+ item.spanX, item.spanY);
lp.cellX = mTargetCell[0];
lp.cellY = mTargetCell[1];
+ lp.cellHSpan = item.spanX;
+ lp.cellVSpan = item.spanY;
cell.setId(LauncherModel.getCellLayoutChildId(container, mDragInfo.screen,
mTargetCell[0], mTargetCell[1], mDragInfo.spanX, mDragInfo.spanY));
@@ -2243,18 +2261,18 @@ public class Workspace extends SmoothPagedView
final LauncherAppWidgetHostView hostView = (LauncherAppWidgetHostView) cell;
AppWidgetProviderInfo pinfo = hostView.getAppWidgetInfo();
if (pinfo.resizeMode != AppWidgetProviderInfo.RESIZE_NONE) {
- final Runnable resizeRunnable = new Runnable() {
+ final Runnable addResizeFrame = new Runnable() {
public void run() {
DragLayer dragLayer = mLauncher.getDragLayer();
dragLayer.addResizeFrame(info, hostView, cellLayout);
}
};
- post(new Runnable() {
+ resizeRunnable = (new Runnable() {
public void run() {
if (!isPageMoving()) {
- resizeRunnable.run();
+ addResizeFrame.run();
} else {
- mDelayedResizeRunnable = resizeRunnable;
+ mDelayedResizeRunnable = addResizeFrame;
}
}
});
@@ -2263,25 +2281,40 @@ public class Workspace extends SmoothPagedView
LauncherModel.moveItemInDatabase(mLauncher, info, container, screen, lp.cellX,
lp.cellY);
+ } else {
+ // If we can't find a drop location, we return the item to its original position
+ CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
+ mTargetCell[0] = lp.cellX;
+ mTargetCell[1] = lp.cellY;
}
}
final CellLayout parent = (CellLayout) cell.getParent().getParent();
-
+ final Runnable finalResizeRunnable = resizeRunnable;
// Prepare it to be animated into its new position
// This must be called after the view has been re-parented
- final Runnable disableHardwareLayersRunnable = new Runnable() {
+ final Runnable onCompleteRunnable = new Runnable() {
@Override
public void run() {
mAnimatingViewIntoPlace = false;
updateChildrenLayersEnabled();
+ if (finalResizeRunnable != null) {
+ finalResizeRunnable.run();
+ }
}
};
mAnimatingViewIntoPlace = true;
if (d.dragView.hasDrawn()) {
- int duration = snapScreen < 0 ? -1 : ADJACENT_SCREEN_DROP_DURATION;
- mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell, duration,
- disableHardwareLayersRunnable, this);
+ final ItemInfo info = (ItemInfo) cell.getTag();
+ if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET) {
+ int animationType = resizeOnDrop ? ANIMATE_INTO_POSITION_AND_RESIZE :
+ ANIMATE_INTO_POSITION_AND_DISAPPEAR;
+ animateWidgetDrop(info, parent, d.dragView,
+ onCompleteRunnable, animationType, cell, false);
+ } else {
+ mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell,
+ onCompleteRunnable);
+ }
} else {
d.deferDragViewCleanupPostAnimation = false;
cell.setVisibility(VISIBLE);
@@ -2430,19 +2463,18 @@ public class Workspace extends SmoothPagedView
// Create the drag outline
// We need to add extra padding to the bitmap to make room for the glow effect
final Canvas canvas = new Canvas();
- final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
- mDragOutline = createExternalDragOutline(canvas, bitmapPadding);
+ mDragOutline = createExternalDragOutline(canvas, DRAG_BITMAP_PADDING);
// Show the current page outlines to indicate that we can accept this drop
showOutlines();
layout.onDragEnter();
- layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1, null, null);
+ layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1, 1, 1, null, null);
return true;
}
case DragEvent.ACTION_DRAG_LOCATION:
// Visualize the drop location
- layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1, null, null);
+ layout.visualizeDropLocation(null, mDragOutline, x, y, 1, 1, 1, 1, null, null);
return true;
case DragEvent.ACTION_DROP: {
// Try and add any shortcuts
@@ -2475,7 +2507,7 @@ public class Workspace extends SmoothPagedView
final PendingAddWidgetInfo createInfo =
new PendingAddWidgetInfo(widgetInfo, mimeType, data);
mLauncher.addAppWidgetFromDrop(createInfo,
- LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentPage, null, pos);
+ LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentPage, null, null, pos);
} else {
// Show the widget picker dialog if there is more than one widget
// that can handle this data type
@@ -2815,10 +2847,16 @@ public class Workspace extends SmoothPagedView
mLastDragOverView = dragOverView;
if (!mCreateUserFolderOnDrop && !isOverFolder) {
+ int minSpanX = item.spanX;
+ int minSpanY = item.spanY;
+ if (item.minSpanX > 0 && item.minSpanY > 0) {
+ minSpanX = item.minSpanX;
+ minSpanY = item.minSpanY;
+ }
mDragTargetLayout.visualizeDropLocation(child, mDragOutline,
(int) mDragViewVisualCenter[0], (int) mDragViewVisualCenter[1],
- item.spanX, item.spanY, d.dragView.getDragVisualizeOffset(),
- d.dragView.getDragRegion());
+ minSpanX, minSpanY, item.spanX, item.spanY,
+ d.dragView.getDragVisualizeOffset(), d.dragView.getDragRegion());
}
}
}
@@ -2939,9 +2977,19 @@ public class Workspace extends SmoothPagedView
findNearestVacantCell = false;
}
}
+ final ItemInfo item = (ItemInfo) d.dragInfo;
+ int minSpanX = item.spanX;
+ int minSpanY = item.spanY;
+ if (item.minSpanX > 0 && item.minSpanY > 0) {
+ minSpanX = item.minSpanX;
+ minSpanY = item.minSpanY;
+ }
if (findNearestVacantCell) {
- mTargetCell = findNearestVacantArea(touchXY[0], touchXY[1], spanX, spanY, null,
- cellLayout, mTargetCell);
+ int[] resultSpan = new int[2];
+ mTargetCell = findNearestVacantArea(touchXY[0], touchXY[1], minSpanX, minSpanY,
+ spanX, spanY, null, cellLayout, mTargetCell, resultSpan);
+ item.spanX = resultSpan[0];
+ item.spanY = resultSpan[1];
}
Runnable onAnimationCompleteRunnable = new Runnable() {
@@ -2951,8 +2999,11 @@ public class Workspace extends SmoothPagedView
// widgets/shortcuts/folders in a slightly different way
switch (pendingInfo.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+ int span[] = new int[2];
+ span[0] = item.spanX;
+ span[1] = item.spanY;
mLauncher.addAppWidgetFromDrop((PendingAddWidgetInfo) pendingInfo,
- container, screen, mTargetCell, null);
+ container, screen, mTargetCell, span, null);
break;
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
mLauncher.processShortcutFromDrop(pendingInfo.componentName,
@@ -2965,9 +3016,15 @@ public class Workspace extends SmoothPagedView
cellLayout.onDragExit();
}
};
-
- animateExternalDrop((PendingAddItemInfo) info, cellLayout, d.dragView,
- onAnimationCompleteRunnable, ANIMATE_INTO_POSITION);
+ View finalView = pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
+ ? ((PendingAddWidgetInfo) pendingInfo).boundWidget : null;
+ int animationStyle = ANIMATE_INTO_POSITION_AND_DISAPPEAR;
+ if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET &&
+ ((PendingAddWidgetInfo) pendingInfo).info.configure != null) {
+ animationStyle = ANIMATE_INTO_POSITION_AND_REMAIN;
+ }
+ animateWidgetDrop(info, cellLayout, d.dragView, onAnimationCompleteRunnable,
+ animationStyle, finalView, true);
} else {
// This is for other drag/drop cases, like dragging from All Apps
View view = null;
@@ -3033,11 +3090,10 @@ public class Workspace extends SmoothPagedView
}
}
- public Bitmap createWidgetBitmap(PendingAddWidgetInfo widgetInfo) {
+ public Bitmap createWidgetBitmap(ItemInfo widgetInfo, View layout) {
int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(widgetInfo.spanX,
widgetInfo.spanY, widgetInfo, false);
- View layout = widgetInfo.boundWidget;
- mLauncher.getDragLayer().removeView(layout);
+ int visibility = layout.getVisibility();
layout.setVisibility(VISIBLE);
int width = MeasureSpec.makeMeasureSpec(unScaledSize[0], MeasureSpec.EXACTLY);
@@ -3050,56 +3106,90 @@ public class Workspace extends SmoothPagedView
layout.layout(0, 0, unScaledSize[0], unScaledSize[1]);
layout.draw(c);
c.setBitmap(null);
+ layout.setVisibility(visibility);
return b;
}
- public void animateExternalDrop(PendingAddItemInfo pendingInfo, CellLayout cellLayout,
- DragView dragView, Runnable onCompleteRunnable, int animationType) {
+ private void getFinalPositionForDropAnimation(int[] loc, float[] scaleXY,
+ DragView dragView, CellLayout layout, ItemInfo info, int[] targetCell, View finalView,
+ boolean external) {
// Now we animate the dragView, (ie. the widget or shortcut preview) into its final
// location and size on the home screen.
- int spanX = pendingInfo.spanX;
- int spanY = pendingInfo.spanY;
- RectF r = estimateItemPosition(cellLayout, pendingInfo,
- mTargetCell[0], mTargetCell[1], spanX, spanY);
- int loc[] = new int[2];
- loc[0] = (int) r.left;
- loc[1] = (int) r.top;
- setFinalTransitionTransform(cellLayout);
+ int spanX = info.spanX;
+ int spanY = info.spanY;
+
+ Rect r = estimateItemPosition(layout, info, targetCell[0], targetCell[1], spanX, spanY);
+ loc[0] = r.left;
+ loc[1] = r.top;
+
+ setFinalTransitionTransform(layout);
float cellLayoutScale =
- mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(cellLayout, loc);
- resetTransitionTransform(cellLayout);
+ mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(layout, loc);
+ resetTransitionTransform(layout);
+ float dragViewScaleX = (1.0f * r.width()) / dragView.getMeasuredWidth();
+ float dragViewScaleY = (1.0f * r.height()) / dragView.getMeasuredHeight();
- float dragViewScaleX = r.width() / dragView.getMeasuredWidth();
- float dragViewScaleY = r.height() / dragView.getMeasuredHeight();
// The animation will scale the dragView about its center, so we need to center about
// the final location.
loc[0] -= (dragView.getMeasuredWidth() - cellLayoutScale * r.width()) / 2;
loc[1] -= (dragView.getMeasuredHeight() - cellLayoutScale * r.height()) / 2;
- float scaleX = dragViewScaleX * cellLayoutScale;
- float scaleY = dragViewScaleY * cellLayoutScale;
+ scaleXY[0] = dragViewScaleX * cellLayoutScale;
+ scaleXY[1] = dragViewScaleY * cellLayoutScale;
+ }
+
+ public void animateWidgetDrop(ItemInfo info, CellLayout cellLayout, DragView dragView,
+ final Runnable onCompleteRunnable, int animationType, final View finalView,
+ boolean external) {
+ Rect from = new Rect();
+ mLauncher.getDragLayer().getViewRectRelativeToSelf(dragView, from);
+
+ int[] finalPos = new int[2];
+ float scaleXY[] = new float[2];
+ getFinalPositionForDropAnimation(finalPos, scaleXY, dragView, cellLayout, info, mTargetCell,
+ finalView, external);
Resources res = mLauncher.getResources();
int duration = res.getInteger(R.integer.config_dropAnimMaxDuration) - 200;
- int animationEnd = DragLayer.ANIMATION_END_REMAIN_VISIBLE;
- if (pendingInfo.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET &&
- (((PendingAddWidgetInfo) pendingInfo).info.configure == null ||
- animationType == COMPLETE_TWO_STAGE_WIDGET_DROP_ANIMATION)) {
- Bitmap crossFadeBitmap = createWidgetBitmap((PendingAddWidgetInfo) pendingInfo);
+ // In the case where we've prebound the widget, we remove it from the DragLayer
+ if (finalView instanceof AppWidgetHostView && external) {
+ mLauncher.getDragLayer().removeView(finalView);
+ }
+ if ((animationType == ANIMATE_INTO_POSITION_AND_RESIZE || external) && finalView != null) {
+ Bitmap crossFadeBitmap = createWidgetBitmap(info, finalView);
dragView.setCrossFadeBitmap(crossFadeBitmap);
dragView.crossFade((int) (duration * 0.8f));
- animationEnd = DragLayer.ANIMATION_END_DISAPPEAR;
- } else {
- scaleX = scaleY = Math.min(scaleX, scaleY);
+ } else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET && external) {
+ scaleXY[0] = scaleXY[1] = Math.min(scaleXY[0], scaleXY[1]);
}
+ DragLayer dragLayer = mLauncher.getDragLayer();
if (animationType == CANCEL_TWO_STAGE_WIDGET_DROP_ANIMATION) {
- mLauncher.getDragLayer().animateViewIntoPosition(dragView, loc, 0f, 0.1f, 0.1f,
+ mLauncher.getDragLayer().animateViewIntoPosition(dragView, finalPos, 0f, 0.1f, 0.1f,
DragLayer.ANIMATION_END_DISAPPEAR, onCompleteRunnable, duration);
} else {
- mLauncher.getDragLayer().animateViewIntoPosition(dragView, loc, 1f, scaleX, scaleY,
- animationEnd, onCompleteRunnable, duration);
+ int endStyle;
+ if (animationType == ANIMATE_INTO_POSITION_AND_REMAIN) {
+ endStyle = DragLayer.ANIMATION_END_REMAIN_VISIBLE;
+ } else {
+ endStyle = DragLayer.ANIMATION_END_DISAPPEAR;;
+ }
+
+ Runnable onComplete = new Runnable() {
+ @Override
+ public void run() {
+ if (finalView != null) {
+ finalView.setVisibility(VISIBLE);
+ }
+ if (onCompleteRunnable != null) {
+ onCompleteRunnable.run();
+ }
+ }
+ };
+ dragLayer.animateViewIntoPosition(dragView, from.left, from.top, finalPos[0],
+ finalPos[1], 1, 1, 1, scaleXY[0], scaleXY[1], onComplete, endStyle,
+ duration, this);
}
}
@@ -3159,7 +3249,19 @@ public class Workspace extends SmoothPagedView
private int[] findNearestVacantArea(int pixelX, int pixelY,
int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle) {
return layout.findNearestVacantArea(
- pixelX, pixelY, spanX, spanY, ignoreView, recycle);
+ pixelX, pixelY, spanX, spanY, spanX, spanY, ignoreView, recycle, null);
+ }
+
+ /**
+ * Calculate the nearest cell where the given object would be dropped.
+ *
+ * pixelX and pixelY should be in the coordinate system of layout
+ */
+ private int[] findNearestVacantArea(int pixelX, int pixelY, int minSpanX, int minSpanY,
+ int spanX, int spanY, View ignoreView, CellLayout layout, int[] recycle,
+ int[] returnSpan) {
+ return layout.findNearestVacantArea(
+ pixelX, pixelY, minSpanX, minSpanY, spanX, spanY, ignoreView, recycle, returnSpan);
}
/**