diff options
author | Adam Cohen <adamcohen@google.com> | 2011-07-14 12:39:48 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-07-14 12:39:48 -0700 |
commit | 6cd835ce0b95aa9d593d0122eab7d7e4da781e23 (patch) | |
tree | fc26c3fbe79e804dcb861f5b6c2b739b65783b90 | |
parent | d74c984fcc61f86160476a2543faff715e3ee2fd (diff) | |
parent | ac8c87687b8e063c981f28cb31bab2cc110f26cc (diff) | |
download | packages_apps_trebuchet-6cd835ce0b95aa9d593d0122eab7d7e4da781e23.zip packages_apps_trebuchet-6cd835ce0b95aa9d593d0122eab7d7e4da781e23.tar.gz packages_apps_trebuchet-6cd835ce0b95aa9d593d0122eab7d7e4da781e23.tar.bz2 |
Merge "Pixel perfect drag animations in workspace and folders, including springloaded"
-rw-r--r-- | src/com/android/launcher2/AppsCustomizePagedView.java | 33 | ||||
-rw-r--r-- | src/com/android/launcher2/DragLayer.java | 46 | ||||
-rw-r--r-- | src/com/android/launcher2/Folder.java | 16 | ||||
-rw-r--r-- | src/com/android/launcher2/FolderIcon.java | 43 | ||||
-rw-r--r-- | src/com/android/launcher2/Workspace.java | 101 |
5 files changed, 120 insertions, 119 deletions
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java index 12fe971..8a4bdc7 100644 --- a/src/com/android/launcher2/AppsCustomizePagedView.java +++ b/src/com/android/launcher2/AppsCustomizePagedView.java @@ -385,37 +385,12 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen protected void determineDraggingStart(android.view.MotionEvent ev) { // Disable dragging by pulling an app down for now. } - private void beginDraggingApplication(View v) { - // Make a copy of the ApplicationInfo - ApplicationInfo appInfo = new ApplicationInfo((ApplicationInfo) v.getTag()); - - // Compose the drag image (top compound drawable, index is 1) - final TextView tv = (TextView) v; - final Drawable icon = tv.getCompoundDrawables()[1]; - Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), - Bitmap.Config.ARGB_8888); - mCanvas.setBitmap(b); - mCanvas.save(); - mCanvas.translate((v.getWidth() - icon.getIntrinsicWidth()) / 2, v.getPaddingTop()); - icon.draw(mCanvas); - mCanvas.restore(); - - // Compose the visible rect of the drag image - Rect dragRect = null; - if (v instanceof TextView) { - int top = v.getPaddingTop(); - int left = (b.getWidth() - mAppIconSize) / 2; - int right = left + mAppIconSize; - int bottom = top + mAppIconSize; - dragRect = new Rect(left, top, right, bottom); - } - // Start the drag - mLauncher.lockScreenOrientation(); - mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b); - mDragController.startDrag(v, b, this, appInfo, DragController.DRAG_ACTION_COPY, dragRect); - b.recycle(); + private void beginDraggingApplication(View v) { + mLauncher.getWorkspace().onDragStartedWithItem(v); + mLauncher.getWorkspace().beginDragShared(v, this); } + private void beginDraggingWidget(View v) { // Get the widget preview as the drag representation ImageView image = (ImageView) v.findViewById(R.id.widget_preview); diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java index 0bdfec1..37abe5a 100644 --- a/src/com/android/launcher2/DragLayer.java +++ b/src/com/android/launcher2/DragLayer.java @@ -26,6 +26,7 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Rect; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.KeyEvent; import android.view.MotionEvent; @@ -34,6 +35,7 @@ import android.view.ViewParent; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.widget.FrameLayout; +import android.widget.TextView; import com.android.launcher.R; @@ -167,12 +169,13 @@ public class DragLayer extends FrameLayout { return mDragController.onTouchEvent(ev); } - public void getDescendantRectRelativeToSelf(View descendant, Rect r) { + public float getDescendantRectRelativeToSelf(View descendant, Rect r) { mTmpXY[0] = 0; mTmpXY[1] = 0; - getDescendantCoordRelativeToSelf(descendant, mTmpXY); + float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY); r.set(mTmpXY[0], mTmpXY[1], mTmpXY[0] + descendant.getWidth(), mTmpXY[1] + descendant.getHeight()); + return scale; } private float getDescendantCoordRelativeToSelf(View descendant, int[] coord) { @@ -315,6 +318,7 @@ public class DragLayer extends FrameLayout { public void animateViewIntoPosition(DragView dragView, final View child) { animateViewIntoPosition(dragView, child, null); } + public void animateViewIntoPosition(DragView dragView, final View child, final Runnable onFinishAnimationRunnable) { ((CellLayoutChildren) child.getParent()).measureChild(child); @@ -324,18 +328,30 @@ public class DragLayer extends FrameLayout { getViewRectRelativeToSelf(dragView, r); int coord[] = new int[2]; - coord[0] = lp.x + (lp.width / 2); - coord[1] = lp.y + (lp.height / 2); + coord[0] = lp.x; + coord[1] = lp.y; // Since the child hasn't necessarily been laid out, we force the lp to be updated with - // the correct coordinates and use these to determine the final location + // the correct coordinates (above) and use these to determine the final location float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord); - int toX = coord[0] - lp.width / 2; - int toY = coord[1] - lp.height / 2; - toX -= (dragView.getWidth() - child.getMeasuredWidth()) / 2; - toY -= (dragView.getHeight() - child.getMeasuredHeight()) / 2; + int toX = coord[0]; + int toY = coord[1]; + if (child instanceof TextView) { + TextView tv = (TextView) child; + Drawable d = tv.getCompoundDrawables()[1]; + + // Center in the y coordinate about the target's drawable + toY += Math.round(scale * tv.getPaddingTop()); + toY -= (dragView.getHeight() - (int) Math.round(scale * d.getIntrinsicHeight())) / 2; + // Center in the x coordinate about the target's drawable + toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2; + } else { + toY -= (Math.round(scale * (dragView.getHeight() - child.getMeasuredHeight()))) / 2; + toX -= (Math.round(scale * (dragView.getMeasuredWidth() + - child.getMeasuredWidth()))) / 2; + } - final int fromX = r.left + (dragView.getWidth() - child.getMeasuredWidth()) / 2; - final int fromY = r.top + (dragView.getHeight() - child.getMeasuredHeight()) / 2; + final int fromX = r.left; + final int fromY = r.top; child.setVisibility(INVISIBLE); child.setAlpha(0); Runnable onCompleteRunnable = new Runnable() { @@ -400,6 +416,10 @@ public class DragLayer extends FrameLayout { mDropAnim.cancel(); } + if (mFadeOutAnim != null) { + mFadeOutAnim.cancel(); + } + mDropView = view; final float initialAlpha = view.getAlpha(); mDropAnim = new ValueAnimator(); @@ -424,8 +444,8 @@ public class DragLayer extends FrameLayout { float motionPercent = motionInterpolator == null ? percent : motionInterpolator.getInterpolation(percent); - mDropViewPos[0] = from.left + (int) ((to.left - from.left) * motionPercent); - mDropViewPos[1] = from.top + (int) ((to.top - from.top) * motionPercent); + mDropViewPos[0] = from.left + (int) Math.round(((to.left - from.left) * motionPercent)); + mDropViewPos[1] = from.top + (int) Math.round(((to.top - from.top) * motionPercent)); mDropViewScale = percent * finalScale + (1 - percent); mDropViewAlpha = alphaPercent * finalAlpha + (1 - alphaPercent) * initialAlpha; invalidate(mDropViewPos[0], mDropViewPos[1], diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java index 78df80f..dd0bffd 100644 --- a/src/com/android/launcher2/Folder.java +++ b/src/com/android/launcher2/Folder.java @@ -90,6 +90,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList private int[] mTargetCell = new int[2]; private int[] mPreviousTargetCell = new int[2]; private int[] mEmptyCell = new int[2]; + private int[] mTempXY = new int[2]; private Alarm mReorderAlarm = new Alarm(); private Alarm mOnExitAlarm = new Alarm(); private TextView mFolderName; @@ -205,14 +206,13 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList } mLauncher.getWorkspace().onDragStartedWithItem(v); - mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY); + mLauncher.getWorkspace().beginDragShared(v, this); mIconDrawable = ((TextView) v).getCompoundDrawables()[1]; mCurrentDragInfo = item; mEmptyCell[0] = item.cellX; mEmptyCell[1] = item.cellY; mCurrentDragView = v; - } return true; } @@ -270,18 +270,6 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList return true; } - public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { - if (!view.isInTouchMode()) { - return false; - } - - ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position); - - mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY); - mLauncher.closeFolder(this); - return true; - } - public void setDragController(DragController dragController) { mDragController = dragController; } diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java index 952916d..93f56fb 100644 --- a/src/com/android/launcher2/FolderIcon.java +++ b/src/com/android/launcher2/FolderIcon.java @@ -24,6 +24,7 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.Paint; import android.graphics.PorterDuff; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -286,12 +287,13 @@ public class FolderIcon extends LinearLayout implements FolderListener { public void performCreateAnimation(final ShortcutInfo destInfo, final View destView, final ShortcutInfo srcInfo, final View srcView, Rect dstRect, - Runnable postAnimationRunnable) { + float scaleRelativeToDragLayer, Runnable postAnimationRunnable) { Drawable animateDrawable = ((TextView) destView).getCompoundDrawables()[1]; computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(), destView.getMeasuredWidth()); + // This will animate the dragView (srcView) into the new folder - onDrop(srcInfo, srcView, dstRect, 1, postAnimationRunnable); + onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable); // This will animate the first item from it's position as an icon into its // position as the first item in the preview @@ -309,8 +311,8 @@ public class FolderIcon extends LinearLayout implements FolderListener { mFolderRingAnimator.animateToNaturalState(); } - private void onDrop(final ShortcutInfo item, View animateView, Rect finalRect, int index, - Runnable postAnimationRunnable) { + private void onDrop(final ShortcutInfo item, View animateView, Rect finalRect, + float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable) { item.cellX = -1; item.cellY = -1; DragLayer dragLayer = mLauncher.getDragLayer(); @@ -319,22 +321,22 @@ public class FolderIcon extends LinearLayout implements FolderListener { Rect to = finalRect; if (to == null) { to = new Rect(); - dragLayer.getDescendantRectRelativeToSelf(this, to); + scaleRelativeToDragLayer = dragLayer.getDescendantRectRelativeToSelf(this, to); } - if (animateView.getMeasuredWidth() != to.width() || - animateView.getMeasuredHeight() != to.height()) { - int offsetX = (animateView.getMeasuredWidth() - to.width()) / 2; - int offsetY = (animateView.getMeasuredHeight() - to.height()) / 2; - to.offset(-offsetX, -offsetY); - } - float scale = adjustFinalScreenRectForIndex(to, index); + int[] center = new int[2]; + float scale = getLocalCenterForIndex(index, center); + center[0] = (int) Math.round(scaleRelativeToDragLayer * center[0]); + center[1] = (int) Math.round(scaleRelativeToDragLayer * center[1]); + + to.offset(center[0] - animateView.getMeasuredWidth() / 2, + center[1] - animateView.getMeasuredHeight() / 2); float finalAlpha = index < NUM_ITEMS_IN_PREVIEW ? 0.5f : 0f; - dragLayer.animateView(animateView, from, to, finalAlpha, scale, DROP_IN_ANIMATION_DURATION, - new DecelerateInterpolator(2), new AccelerateInterpolator(2), postAnimationRunnable, - false); + dragLayer.animateView(animateView, from, to, finalAlpha, scale * scaleRelativeToDragLayer, + DROP_IN_ANIMATION_DURATION, new DecelerateInterpolator(2), + new AccelerateInterpolator(2), postAnimationRunnable, false); postDelayed(new Runnable() { public void run() { addItem(item); @@ -350,7 +352,7 @@ public class FolderIcon extends LinearLayout implements FolderListener { } else { item = (ShortcutInfo) d.dragInfo; } - onDrop(item, d.dragView, null, mInfo.contents.size(), d.postAnimationRunnable); + onDrop(item, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable); } public DropTarget getDropTargetDelegate(DragObject d) { @@ -398,15 +400,16 @@ public class FolderIcon extends LinearLayout implements FolderListener { Drawable drawable; } - private float adjustFinalScreenRectForIndex(Rect r, int index) { + private float getLocalCenterForIndex(int index, int[] center) { mParams = computePreviewItemDrawingParams(Math.min(NUM_ITEMS_IN_PREVIEW, index), mParams); mParams.transX += mPreviewOffsetX; mParams.transY += mPreviewOffsetY; - float offsetX = mParams.transX + (mParams.scale * mIntrinsicIconSize) / 2 - mTotalWidth / 2; - float offsetY = mParams.transY + (mParams.scale * mIntrinsicIconSize) / 2 - mTotalWidth / 2; + float offsetX = mParams.transX + (mParams.scale * mIntrinsicIconSize) / 2; + float offsetY = mParams.transY + (mParams.scale * mIntrinsicIconSize) / 2; - r.offset((int) offsetX, (int) offsetY); + center[0] = (int) Math.round(offsetX); + center[1] = (int) Math.round(offsetY); return mParams.scale; } diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index 4b38a43..701b33b 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -39,6 +39,7 @@ import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Camera; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; @@ -1828,32 +1829,57 @@ public class Workspace extends SmoothPagedView * @param destCanvas the canvas to draw on * @param padding the horizontal and vertical padding to use when drawing */ - private void drawDragView(View v, Canvas destCanvas, int padding) { + private void drawDragView(View v, Canvas destCanvas, int padding, boolean pruneToDrawable) { final Rect clipRect = mTempRect; v.getDrawingRect(clipRect); - // For a TextView, adjust the clip rect so that we don't include the text label - if (v instanceof BubbleTextView) { - final BubbleTextView tv = (BubbleTextView) v; - clipRect.bottom = tv.getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V + - tv.getLayout().getLineTop(0); - } else if (v instanceof TextView) { - final TextView tv = (TextView) v; - clipRect.bottom = tv.getExtendedPaddingTop() - tv.getCompoundDrawablePadding() + - tv.getLayout().getLineTop(0); - } else if (v instanceof FolderIcon) { - clipRect.bottom = getResources().getDimensionPixelSize(R.dimen.folder_preview_size); + destCanvas.save(); + if (v instanceof TextView && pruneToDrawable) { + Drawable d = ((TextView) v).getCompoundDrawables()[1]; + clipRect.set(0, 0, d.getIntrinsicWidth() + padding, d.getIntrinsicHeight() + padding); + destCanvas.translate(padding / 2, padding / 2); + d.draw(destCanvas); + } else { + if (v instanceof FolderIcon) { + clipRect.bottom = getResources().getDimensionPixelSize(R.dimen.folder_preview_size); + } else if (v instanceof BubbleTextView) { + final BubbleTextView tv = (BubbleTextView) v; + clipRect.bottom = tv.getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V + + tv.getLayout().getLineTop(0); + } else if (v instanceof TextView) { + final TextView tv = (TextView) v; + clipRect.bottom = tv.getExtendedPaddingTop() - tv.getCompoundDrawablePadding() + + tv.getLayout().getLineTop(0); + } + destCanvas.translate(-v.getScrollX() + padding / 2, -v.getScrollY() + padding / 2); + destCanvas.clipRect(clipRect, Op.REPLACE); + v.draw(destCanvas); } + destCanvas.restore(); + } - // Draw the View into the bitmap. - // The translate of scrollX and scrollY is necessary when drawing TextViews, because - // they set scrollX and scrollY to large values to achieve centered text + /** + * Returns a new bitmap to show when the given View is being dragged around. + * Responsibility for the bitmap is transferred to the caller. + */ + public Bitmap createDragBitmap(View v, Canvas canvas, int padding) { + final int outlineColor = getResources().getColor(R.color.drag_outline_color); + Bitmap b; - destCanvas.save(); - destCanvas.translate(-v.getScrollX() + padding / 2, -v.getScrollY() + padding / 2); - destCanvas.clipRect(clipRect, Op.REPLACE); - v.draw(destCanvas); - destCanvas.restore(); + if (v instanceof TextView) { + Drawable d = ((TextView) v).getCompoundDrawables()[1]; + b = Bitmap.createBitmap(d.getIntrinsicWidth() + padding, + d.getIntrinsicHeight() + padding, Bitmap.Config.ARGB_8888); + } else { + b = Bitmap.createBitmap( + v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888); + } + + canvas.setBitmap(b); + drawDragView(v, canvas, padding, true); + mOutlineHelper.applyOuterBlur(b, canvas, outlineColor); + + return b; } /** @@ -1866,7 +1892,7 @@ public class Workspace extends SmoothPagedView v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888); canvas.setBitmap(b); - drawDragView(v, canvas, padding); + drawDragView(v, canvas, padding, false); mOutlineHelper.applyMediumExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor); return b; } @@ -1920,23 +1946,6 @@ public class Workspace extends SmoothPagedView return b; } - /** - * Returns a new bitmap to show when the given View is being dragged around. - * Responsibility for the bitmap is transferred to the caller. - */ - private Bitmap createDragBitmap(View v, Canvas canvas, int padding) { - final int outlineColor = getResources().getColor(R.color.drag_outline_color); - final Bitmap b = Bitmap.createBitmap( - mDragOutline.getWidth(), mDragOutline.getHeight(), Bitmap.Config.ARGB_8888); - - canvas.setBitmap(b); - canvas.drawBitmap(mDragOutline, 0, 0, null); - drawDragView(v, canvas, padding); - mOutlineHelper.applyOuterBlur(b, canvas, outlineColor); - - return b; - } - void startDrag(CellLayout.CellInfo cellInfo) { View child = cellInfo.cell; @@ -1960,9 +1969,15 @@ public class Workspace extends SmoothPagedView // The outline is used to visualize where the item will land if dropped mDragOutline = createDragOutline(child, canvas, bitmapPadding); + beginDragShared(child, this); + } + + public void beginDragShared(View child, DragSource source) { + // 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, canvas, bitmapPadding); + final Bitmap b = createDragBitmap(child, new Canvas(), bitmapPadding); final int bmpWidth = b.getWidth(); final int bmpHeight = b.getHeight(); @@ -1984,10 +1999,10 @@ public class Workspace extends SmoothPagedView dragRect = new Rect(0, 0, child.getWidth(), previewSize); } - mLauncher.lockScreenOrientation(); - mDragController.startDrag(b, dragLayerX, dragLayerY, this, child.getTag(), + mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(), DragController.DRAG_ACTION_MOVE, dragRect); b.recycle(); + mLauncher.lockScreenOrientation(); } void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY, @@ -2106,7 +2121,7 @@ public class Workspace extends SmoothPagedView } Rect folderLocation = new Rect(); - mLauncher.getDragLayer().getDescendantRectRelativeToSelf(v, folderLocation); + float scale = mLauncher.getDragLayer().getDescendantRectRelativeToSelf(v, folderLocation); target.removeView(v); FolderIcon fi = mLauncher.addFolder(screen, targetCell[0], targetCell[1]); @@ -2115,7 +2130,7 @@ public class Workspace extends SmoothPagedView sourceInfo.cellX = -1; sourceInfo.cellY = -1; - fi.performCreateAnimation(destInfo, v, sourceInfo, dragView, folderLocation, + fi.performCreateAnimation(destInfo, v, sourceInfo, dragView, folderLocation, scale, postAnimationRunnable); return true; } |