diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index e6f8a85e52..21a8fd406e 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -46,6 +46,7 @@ import android.widget.TextView; import com.android.launcher3.Launcher.OnResumeCallback; import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.dot.DotInfo; +import com.android.launcher3.dragndrop.DraggableView; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.graphics.IconPalette; import com.android.launcher3.graphics.IconShape; @@ -65,7 +66,7 @@ import java.text.NumberFormat; * too aggressive. */ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, OnResumeCallback, - IconLabelDotView { + IconLabelDotView, DraggableView { private static final int DISPLAY_WORKSPACE = 0; private static final int DISPLAY_ALL_APPS = 1; @@ -103,7 +104,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, private final ActivityContext mActivity; private Drawable mIcon; - private final boolean mCenterVertically; + private boolean mCenterVertically; private final int mDisplay; @@ -701,4 +702,24 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, public int getIconSize() { return mIconSize; } + + @Override + public int getViewType() { + return DRAGGABLE_ICON; + } + + @Override + public void getVisualDragBounds(Rect bounds) { + DeviceProfile grid = mActivity.getDeviceProfile(); + BubbleTextView.getIconBounds(this, bounds, grid.iconSizePx); + } + + @Override + public void prepareDrawDragView() { + if (getIcon() instanceof FastBitmapDrawable) { + FastBitmapDrawable icon = (FastBitmapDrawable) getIcon(); + icon.setScale(1f); + } + setForceHideDot(true); + } } diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index e3eb38792a..6c562cfac2 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -58,6 +58,7 @@ import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.PropertyListBuilder; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.dragndrop.DraggableView; import com.android.launcher3.folder.PreviewBackground; import com.android.launcher3.graphics.DragPreviewProvider; import com.android.launcher3.graphics.RotationMode; @@ -105,6 +106,11 @@ public class CellLayout extends ViewGroup implements Transposable { @Thunk final int[] mTmpPoint = new int[2]; @Thunk final int[] mTempLocation = new int[2]; + // Used to visualize / debug the Grid of the CellLayout + private static final boolean VISUALIZE_GRID = false; + private Rect mVisualizeGridRect = new Rect(); + private Paint mVisualizeGridPaint = new Paint(); + private GridOccupancy mOccupied; private GridOccupancy mTmpOccupied; @@ -483,6 +489,37 @@ public class CellLayout extends ViewGroup implements Transposable { mFolderLeaveBehind.drawLeaveBehind(canvas); canvas.restore(); } + + if (VISUALIZE_GRID) { + visualizeGrid(canvas); + } + } + + protected void visualizeGrid(Canvas canvas) { + mVisualizeGridRect.set(0, 0, mCellWidth, mCellHeight); + mVisualizeGridPaint.setStrokeWidth(4); + + for (int i = 0; i < mCountX; i++) { + for (int j = 0; j < mCountY; j++) { + canvas.save(); + + int transX = i * mCellWidth; + int transY = j * mCellHeight; + + canvas.translate(getPaddingLeft() + transX, getPaddingTop() + transY); + + mVisualizeGridPaint.setStyle(Paint.Style.FILL); + mVisualizeGridPaint.setColor(Color.argb(80, 255, 100, 100)); + + canvas.drawRect(mVisualizeGridRect, mVisualizeGridPaint); + + mVisualizeGridPaint.setStyle(Paint.Style.STROKE); + mVisualizeGridPaint.setColor(Color.argb(255, 255, 100, 100)); + + canvas.drawRect(mVisualizeGridRect, mVisualizeGridPaint); + canvas.restore(); + } + } } @Override @@ -949,8 +986,8 @@ public class CellLayout extends ViewGroup implements Transposable { return false; } - void visualizeDropLocation(View v, DragPreviewProvider outlineProvider, int cellX, int cellY, - int spanX, int spanY, boolean resize, DropTarget.DragObject dragObject) { + void visualizeDropLocation(DraggableView v, DragPreviewProvider outlineProvider, int cellX, int + cellY, int spanX, int spanY, boolean resize, DropTarget.DragObject dragObject) { final int oldDragCellX = mDragCell[0]; final int oldDragCellY = mDragCell[1]; @@ -960,9 +997,6 @@ public class CellLayout extends ViewGroup implements Transposable { Bitmap dragOutline = outlineProvider.generatedDragOutline; if (cellX != oldDragCellX || cellY != oldDragCellY) { - Point dragOffset = dragObject.dragView.getDragVisualizeOffset(); - Rect dragRegion = dragObject.dragView.getDragRegion(); - mDragCell[0] = cellX; mDragCell[1] = cellY; @@ -971,50 +1005,27 @@ public class CellLayout extends ViewGroup implements Transposable { mDragOutlineCurrent = (oldIndex + 1) % mDragOutlines.length; Rect r = mDragOutlines[mDragOutlineCurrent]; + cellToRect(cellX, cellY, spanX, spanY, r); + int left = r.left; + int top = r.top; + + int width = dragOutline.getWidth(); + int height = dragOutline.getHeight(); + if (resize) { - cellToRect(cellX, cellY, spanX, spanY, r); - if (v instanceof LauncherAppWidgetHostView) { - DeviceProfile profile = mActivity.getWallpaperDeviceProfile(); - Utilities.shrinkRect(r, profile.appWidgetScale.x, profile.appWidgetScale.y); - } - } else { - // Find the top left corner of the rect the object will occupy - final int[] topLeft = mTmpPoint; - cellToPoint(cellX, cellY, topLeft); - - int left = topLeft[0]; - int top = topLeft[1]; - - if (v != null && dragOffset == null) { - // When drawing the drag outline, it did not account for margin offsets - // added by the view's parent. - MarginLayoutParams lp = (MarginLayoutParams) v.getLayoutParams(); - left += lp.leftMargin; - top += lp.topMargin; - - // Offsets due to the size difference between the View and the dragOutline. - // There is a size difference to account for the outer blur, which may lie - // outside the bounds of the view. - top += ((mCellHeight * spanY) - dragOutline.getHeight()) / 2; - // We center about the x axis - left += ((mCellWidth * spanX) - dragOutline.getWidth()) / 2; - } else { - if (dragOffset != null && dragRegion != null) { - // Center the drag region *horizontally* in the cell and apply a drag - // outline offset - left += dragOffset.x + ((mCellWidth * spanX) - dragRegion.width()) / 2; - int cHeight = getShortcutsAndWidgets().getCellContentHeight(); - int cellPaddingY = (int) Math.max(0, ((mCellHeight - cHeight) / 2f)); - top += dragOffset.y + cellPaddingY; - } else { - // Center the drag outline in the cell - left += ((mCellWidth * spanX) - dragOutline.getWidth()) / 2; - top += ((mCellHeight * spanY) - dragOutline.getHeight()) / 2; - } - } - r.set(left, top, left + dragOutline.getWidth(), top + dragOutline.getHeight()); + width = r.width(); + height = r.height(); } + if (v != null && v.getViewType() == DraggableView.DRAGGABLE_ICON) { + left += ((mCellWidth * spanX) - dragOutline.getWidth()) / 2; + int cHeight = getShortcutsAndWidgets().getCellContentHeight(); + int cellPaddingY = (int) Math.max(0, ((mCellHeight - cHeight) / 2f)); + top += cellPaddingY; + } + + r.set(left, top, left + width, top + height); + Utilities.scaleRectAboutCenter(r, mChildScale); mDragOutlineAnims[mDragOutlineCurrent].setTag(dragOutline); mDragOutlineAnims[mDragOutlineCurrent].animateIn(); @@ -1900,7 +1911,7 @@ public class CellLayout extends ViewGroup implements Transposable { // This method starts or changes the reorder preview animations private void beginOrAdjustReorderPreviewAnimations(ItemConfiguration solution, - View dragView, int delay, int mode) { + View dragView, int mode) { int childCount = mShortcutsAndWidgets.getChildCount(); for (int i = 0; i < childCount; i++) { View child = mShortcutsAndWidgets.getChildAt(i); @@ -1967,6 +1978,8 @@ public class CellLayout extends ViewGroup implements Transposable { this.child = child; this.mode = mode; + + // TODO issue! setInitialAnimationValues(false); finalScale = (mChildScale - (CHILD_DIVIDEND / child.getWidth())) * initScale; finalDeltaX = initDeltaX; @@ -2162,6 +2175,8 @@ public class CellLayout extends ViewGroup implements Transposable { */ private void getDirectionVectorForDrop(int dragViewCenterX, int dragViewCenterY, int spanX, int spanY, View dragView, int[] resultDirection) { + + //TODO(adamcohen) b/151776141 use the items visual center for the direction vector int[] targetDestination = new int[2]; findNearestArea(dragViewCenterX, dragViewCenterY, spanX, spanY, targetDestination); @@ -2272,7 +2287,7 @@ public class CellLayout extends ViewGroup implements Transposable { setItemPlacementDirty(false); } else { beginOrAdjustReorderPreviewAnimations(swapSolution, dragView, - REORDER_ANIMATION_DURATION, ReorderPreviewAnimation.MODE_PREVIEW); + ReorderPreviewAnimation.MODE_PREVIEW); } mShortcutsAndWidgets.requestLayout(); } @@ -2326,7 +2341,7 @@ public class CellLayout extends ViewGroup implements Transposable { if (mode == MODE_SHOW_REORDER_HINT) { if (finalSolution != null) { - beginOrAdjustReorderPreviewAnimations(finalSolution, dragView, 0, + beginOrAdjustReorderPreviewAnimations(finalSolution, dragView, ReorderPreviewAnimation.MODE_HINT); result[0] = finalSolution.cellX; result[1] = finalSolution.cellY; @@ -2366,7 +2381,7 @@ public class CellLayout extends ViewGroup implements Transposable { setItemPlacementDirty(false); } else { beginOrAdjustReorderPreviewAnimations(finalSolution, dragView, - REORDER_ANIMATION_DURATION, ReorderPreviewAnimation.MODE_PREVIEW); + ReorderPreviewAnimation.MODE_PREVIEW); } } } else { diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java index a32fd1239f..43ec5a6949 100644 --- a/src/com/android/launcher3/DropTarget.java +++ b/src/com/android/launcher3/DropTarget.java @@ -23,6 +23,7 @@ import com.android.launcher3.accessibility.DragViewStateAnnouncer; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.dragndrop.DragView; +import com.android.launcher3.dragndrop.DraggableView; import com.android.launcher3.folder.FolderNameProvider; /** @@ -72,6 +73,10 @@ public interface DropTarget { public FolderNameProvider folderNameProvider; + /** The source view (ie. icon, widget etc.) that is being dragged and which the + * DragView represents. May be an actual View class or a virtual stand-in */ + public DraggableView originalView = null; + public DragObject(Context context) { if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) { folderNameProvider = FolderNameProvider.newInstance(context); diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java index 1bd82633eb..c07dd9d3f8 100644 --- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java +++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java @@ -145,38 +145,46 @@ public class ShortcutAndWidgetContainer extends ViewGroup { final View child = getChildAt(i); if (child.getVisibility() != GONE) { CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); - - if (child instanceof LauncherAppWidgetHostView) { - LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) child; - - // Scale and center the widget to fit within its cells. - DeviceProfile profile = mActivity.getDeviceProfile(); - float scaleX = profile.appWidgetScale.x; - float scaleY = profile.appWidgetScale.y; - - lahv.setScaleToFit(Math.min(scaleX, scaleY)); - lahv.setTranslationForCentering(-(lp.width - (lp.width * scaleX)) / 2.0f, - -(lp.height - (lp.height * scaleY)) / 2.0f); - } - - int childLeft = lp.x; - int childTop = lp.y; - child.layout(childLeft, childTop, childLeft + lp.width, childTop + lp.height); - - if (lp.dropped) { - lp.dropped = false; - - final int[] cellXY = mTmpCellXY; - getLocationOnScreen(cellXY); - mWallpaperManager.sendWallpaperCommand(getWindowToken(), - WallpaperManager.COMMAND_DROP, - cellXY[0] + childLeft + lp.width / 2, - cellXY[1] + childTop + lp.height / 2, 0, null); - } + layoutChild(child); } } } + /** + * Core logic to layout a child for this ViewGroup. + */ + public void layoutChild(View child) { + CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); + if (child instanceof LauncherAppWidgetHostView) { + LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) child; + + // Scale and center the widget to fit within its cells. + DeviceProfile profile = mActivity.getDeviceProfile(); + float scaleX = profile.appWidgetScale.x; + float scaleY = profile.appWidgetScale.y; + + lahv.setScaleToFit(Math.min(scaleX, scaleY)); + lahv.setTranslationForCentering(-(lp.width - (lp.width * scaleX)) / 2.0f, + -(lp.height - (lp.height * scaleY)) / 2.0f); + } + + int childLeft = lp.x; + int childTop = lp.y; + child.layout(childLeft, childTop, childLeft + lp.width, childTop + lp.height); + + if (lp.dropped) { + lp.dropped = false; + + final int[] cellXY = mTmpCellXY; + getLocationOnScreen(cellXY); + mWallpaperManager.sendWallpaperCommand(getWindowToken(), + WallpaperManager.COMMAND_DROP, + cellXY[0] + childLeft + lp.width / 2, + cellXY[1] + childTop + lp.height / 2, 0, null); + } + } + + @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.getAction() == ACTION_DOWN && getAlpha() == 0) { diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index ead6018505..d5517765a6 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -70,6 +70,7 @@ import com.android.launcher3.dragndrop.DragController; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.dragndrop.DragView; +import com.android.launcher3.dragndrop.DraggableView; import com.android.launcher3.dragndrop.SpringLoadedDragController; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; @@ -81,7 +82,6 @@ import com.android.launcher3.icons.BitmapRenderer; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.pageindicators.WorkspacePageIndicator; import com.android.launcher3.popup.PopupContainerWithArrow; -import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.touch.WorkspaceTouchListener; import com.android.launcher3.userevent.nano.LauncherLogProto.Action; @@ -1465,12 +1465,17 @@ public class Workspace extends PagedView + "View: " + child + " tag: " + child.getTag(); throw new IllegalStateException(msg); } - beginDragShared(child, source, (ItemInfo) dragObject, + beginDragShared(child, null, source, (ItemInfo) dragObject, new DragPreviewProvider(child), options); } - public DragView beginDragShared(View child, DragSource source, ItemInfo dragObject, - DragPreviewProvider previewProvider, DragOptions dragOptions) { + /** + * Core functionality for beginning a drag operation for an item that will be dropped within + * the workspace + */ + public DragView beginDragShared(View child, DraggableView draggableView, DragSource source, + ItemInfo dragObject, DragPreviewProvider previewProvider, DragOptions dragOptions) { + float iconScale = 1f; if (child instanceof BubbleTextView) { Drawable icon = ((BubbleTextView) child).getIcon(); @@ -1479,41 +1484,36 @@ public class Workspace extends PagedView } } + // Clear the pressed state if necessary child.clearFocus(); child.setPressed(false); + if (child instanceof BubbleTextView) { + BubbleTextView icon = (BubbleTextView) child; + icon.clearPressedBackground(); + } + mOutlineProvider = previewProvider; // The drag bitmap follows the touch point around on the screen final Bitmap b = previewProvider.createDragBitmap(); int halfPadding = previewProvider.previewPadding / 2; - float scale = previewProvider.getScaleAndPosition(b, mTempXY); int dragLayerX = mTempXY[0]; int dragLayerY = mTempXY[1]; - DeviceProfile grid = mLauncher.getDeviceProfile(); Point dragVisualizeOffset = null; - Rect dragRect = null; - if (child instanceof BubbleTextView) { - dragRect = new Rect(); - BubbleTextView.getIconBounds(child, dragRect, grid.iconSizePx); + Rect dragRect = new Rect(); + + if (draggableView == null && child instanceof DraggableView) { + draggableView = (DraggableView) child; + } + + if (draggableView != null) { + draggableView.getVisualDragBounds(dragRect); dragLayerY += dragRect.top; - // Note: The dragRect is used to calculate drag layer offsets, but the - // dragVisualizeOffset in addition to the dragRect (the size) to position the outline. - dragVisualizeOffset = new Point(- halfPadding, halfPadding); - } else if (child instanceof FolderIcon) { - int previewSize = grid.folderIconSizePx; - dragVisualizeOffset = new Point(- halfPadding, halfPadding - child.getPaddingTop()); - dragRect = new Rect(0, child.getPaddingTop(), child.getWidth(), previewSize); - } else if (previewProvider instanceof ShortcutDragPreviewProvider) { dragVisualizeOffset = new Point(- halfPadding, halfPadding); } - // Clear the pressed state if necessary - if (child instanceof BubbleTextView) { - BubbleTextView icon = (BubbleTextView) child; - icon.clearPressedBackground(); - } if (child.getParent() instanceof ShortcutAndWidgetContainer) { mDragSourceInternal = (ShortcutAndWidgetContainer) child.getParent(); @@ -1524,13 +1524,13 @@ public class Workspace extends PagedView .showForIcon((BubbleTextView) child); if (popupContainer != null) { dragOptions.preDragCondition = popupContainer.createPreDragCondition(); - mLauncher.getUserEventDispatcher().resetElapsedContainerMillis("dragging started"); } } - DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source, - dragObject, dragVisualizeOffset, dragRect, scale * iconScale, scale, dragOptions); + DragView dv = mDragController.startDrag(b, draggableView, dragLayerX, dragLayerY, source, + dragObject, dragVisualizeOffset, dragRect, scale * iconScale, + scale, dragOptions); dv.setIntrinsicIconScaleFactor(dragOptions.intrinsicIconScaleFactor); return dv; } @@ -2203,7 +2203,7 @@ public class Workspace extends PagedView item.spanY, child, mTargetCell); if (!nearestDropOccupied) { - mDragTargetLayout.visualizeDropLocation(child, mOutlineProvider, + mDragTargetLayout.visualizeDropLocation(d.originalView, mOutlineProvider, mTargetCell[0], mTargetCell[1], item.spanX, item.spanY, false, d); } else if ((mDragMode == DRAG_MODE_NONE || mDragMode == DRAG_MODE_REORDER) && !mReorderAlarm.alarmPending() && (mLastReorderX != reorderX || @@ -2297,7 +2297,8 @@ public class Workspace extends PagedView private void manageFolderFeedback(CellLayout targetLayout, int[] targetCell, float distance, DragObject dragObject) { if (distance > mMaxDistanceForFolderCreation) { - if (mDragMode != DRAG_MODE_NONE) { + if ((mDragMode == DRAG_MODE_ADD_TO_FOLDER + || mDragMode == DRAG_MODE_CREATE_FOLDER)) { setDragMode(DRAG_MODE_NONE); } return; @@ -2413,7 +2414,7 @@ public class Workspace extends PagedView } boolean resize = resultSpan[0] != spanX || resultSpan[1] != spanY; - mDragTargetLayout.visualizeDropLocation(child, mOutlineProvider, + mDragTargetLayout.visualizeDropLocation(dragObject.originalView, mOutlineProvider, mTargetCell[0], mTargetCell[1], resultSpan[0], resultSpan[1], resize, dragObject); } } diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java index de7bc6d0e2..ffaada1379 100644 --- a/src/com/android/launcher3/dragndrop/DragController.java +++ b/src/com/android/launcher3/dragndrop/DragController.java @@ -140,6 +140,8 @@ public class DragController implements DragDriver.EventListener, TouchController * * @param b The bitmap to display as the drag image. It will be re-scaled to the * enlarged size. + * @param originalView The source view (ie. icon, widget etc.) that is being dragged + * and which the DragView represents * @param dragLayerX The x position in the DragLayer of the left-top of the bitmap. * @param dragLayerY The y position in the DragLayer of the left-top of the bitmap. * @param source An object representing where the drag originated @@ -147,7 +149,7 @@ public class DragController implements DragDriver.EventListener, TouchController * @param dragRegion Coordinates within the bitmap b for the position of item being dragged. * Makes dragging feel more precise, e.g. you can clip out a transparent border */ - public DragView startDrag(Bitmap b, int dragLayerX, int dragLayerY, + public DragView startDrag(Bitmap b, DraggableView originalView, int dragLayerX, int dragLayerY, DragSource source, ItemInfo dragInfo, Point dragOffset, Rect dragRegion, float initialDragViewScale, float dragViewScaleOnDrop, DragOptions options) { if (PROFILE_DRAWING_DURING_DRAG) { @@ -173,6 +175,7 @@ public class DragController implements DragDriver.EventListener, TouchController mLastDropTarget = null; mDragObject = new DropTarget.DragObject(mLauncher.getApplicationContext()); + mDragObject.originalView = originalView; mIsInPreDrag = mOptions.preDragCondition != null && !mOptions.preDragCondition.shouldStartDrag(0); diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java index 369bf283b1..409a1d5434 100644 --- a/src/com/android/launcher3/dragndrop/DragLayer.java +++ b/src/com/android/launcher3/dragndrop/DragLayer.java @@ -41,7 +41,6 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.animation.Interpolator; import android.widget.FrameLayout; -import android.widget.TextView; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.CellLayout; @@ -52,7 +51,6 @@ import com.android.launcher3.ShortcutAndWidgetContainer; import com.android.launcher3.Workspace; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.folder.Folder; -import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.graphics.OverviewScrim; import com.android.launcher3.graphics.RotationMode; import com.android.launcher3.graphics.WorkspaceAndHotseatScrim; @@ -90,6 +88,8 @@ public class DragLayer extends BaseDragLayer { private int mTopViewIndex; private int mChildCountOnLastUpdate = -1; + private Rect mTmpRect = new Rect(); + // Related to adjacent page hints private final ViewGroupFocusHelper mFocusIndicatorHelper; private final WorkspaceAndHotseatScrim mWorkspaceScrim; @@ -254,59 +254,46 @@ public class DragLayer extends BaseDragLayer { public void animateViewIntoPosition(DragView dragView, final View child, int duration, View anchorView) { + ShortcutAndWidgetContainer parentChildren = (ShortcutAndWidgetContainer) child.getParent(); CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child.getLayoutParams(); parentChildren.measureChild(child); + parentChildren.layoutChild(child); - Rect r = new Rect(); - getViewRectRelativeToSelf(dragView, r); + getViewRectRelativeToSelf(dragView, mTmpRect); + final int fromX = mTmpRect.left; + final int fromY = mTmpRect.top; float coord[] = new float[2]; float childScale = child.getScaleX(); + coord[0] = lp.x + (child.getMeasuredWidth() * (1 - childScale) / 2); coord[1] = lp.y + (child.getMeasuredHeight() * (1 - childScale) / 2); // Since the child hasn't necessarily been laid out, we force the lp to be updated with // the correct coordinates (above) and use these to determine the final location float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord); + // We need to account for the scale of the child itself, as the above only accounts for // for the scale in parents. scale *= childScale; int toX = Math.round(coord[0]); int toY = Math.round(coord[1]); float toScale = scale; - if (child instanceof TextView) { - TextView tv = (TextView) child; - // Account for the source scale of the icon (ie. from AllApps to Workspace, in which - // the workspace may have smaller icon bounds). - toScale = scale / dragView.getIntrinsicIconScaleFactor(); - // The child may be scaled (always about the center of the view) so to account for it, - // we have to offset the position by the scaled size. Once we do that, we can center - // the drag view about the scaled child view. - // padding will remain constant (does not scale with size) - toY += tv.getPaddingTop(); - toY -= dragView.getMeasuredHeight() * (1 - toScale) / 2; - if (dragView.getDragVisualizeOffset() != null) { - toY -= Math.round(toScale * dragView.getDragVisualizeOffset().y); - } + if (child instanceof DraggableView) { + DraggableView d = (DraggableView) child; + d.getVisualDragBounds(mTmpRect); - toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2; - } else if (child instanceof FolderIcon) { - // Account for holographic blur padding on the drag view - toY += Math.round(scale * (child.getPaddingTop() - dragView.getDragRegionTop())); - toY -= scale * dragView.getBlurSizeOutline() / 2; - toY -= (1 - scale) * dragView.getMeasuredHeight() / 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; + // This accounts for the offset of the DragView created by scaling it about its + // center as it animates into place. + float scaleShiftX = dragView.getMeasuredWidth() * (1 - scale) / 2; + float scaleShiftY = dragView.getMeasuredHeight() * (1 - scale) / 2; + + toX += scale * (mTmpRect.left - dragView.getBlurSizeOutline() / 2) - scaleShiftX; + toY += scale * (mTmpRect.top - dragView.getBlurSizeOutline() / 2) - scaleShiftY; } - final int fromX = r.left; - final int fromY = r.top; child.setVisibility(INVISIBLE); Runnable onCompleteRunnable = () -> child.setVisibility(VISIBLE); animateViewIntoPosition(dragView, fromX, fromY, toX, toY, 1, 1, 1, toScale, toScale, diff --git a/src/com/android/launcher3/dragndrop/DraggableView.java b/src/com/android/launcher3/dragndrop/DraggableView.java new file mode 100644 index 0000000000..df9990278a --- /dev/null +++ b/src/com/android/launcher3/dragndrop/DraggableView.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2020 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.dragndrop; + +import android.graphics.Rect; + +/** + * Interface defining methods required for drawing and previewing DragViews, drag previews, and + * related animations + */ +public interface DraggableView { + int DRAGGABLE_ICON = 0; + int DRAGGABLE_WIDGET = 1; + + /** + * Static ctr for a simple instance which just returns the view type. + */ + static DraggableView ofType(int type) { + return () -> type; + } + + /** + * Certain handling of DragViews depend only on whether this is an Icon Type item or a Widget + * Type item. + * + * @return DRAGGABLE_ICON or DRAGGABLE_WIDGET as appropriate + */ + int getViewType(); + + /** + * Before rendering as a DragView bitmap, some views need a preparation step. + */ + default void prepareDrawDragView() { } + + /** + * If an actual View subclass, this method returns the rectangle (within the View's coordinates) + * of the visual region that should get dragged. This is used to extract exactly that element + * as well as to offset that element as appropriate for various animations + * + * @param bounds Visual bounds in the views coordinates will be written here. + */ + default void getVisualDragBounds(Rect bounds) { } +} diff --git a/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java b/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java index 0bb3fbac52..ea1fbdb583 100644 --- a/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java +++ b/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java @@ -20,10 +20,10 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import android.annotation.TargetApi; import android.graphics.Bitmap; -import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Path; import android.graphics.Point; +import android.graphics.Rect; import android.graphics.drawable.AdaptiveIconDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; @@ -33,7 +33,6 @@ import android.util.Log; import androidx.annotation.Nullable; import com.android.launcher3.Launcher; -import com.android.launcher3.R; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.folder.PreviewBackground; import com.android.launcher3.graphics.ShiftedBitmapDrawable; @@ -50,6 +49,7 @@ public class FolderAdaptiveIcon extends AdaptiveIconDrawable { private final Drawable mBadge; private final Path mMask; private final ConstantState mConstantState; + private static final Rect sTmpRect = new Rect(); private FolderAdaptiveIcon(Drawable bg, Drawable fg, Drawable badge, Path mask) { super(bg, fg); @@ -72,23 +72,14 @@ public class FolderAdaptiveIcon extends AdaptiveIconDrawable { public static @Nullable FolderAdaptiveIcon createFolderAdaptiveIcon( Launcher launcher, int folderId, Point dragViewSize) { Preconditions.assertNonUiThread(); - int margin = launcher.getResources() - .getDimensionPixelSize(R.dimen.blur_size_medium_outline); - - // Allocate various bitmaps on the background thread, because why not! - int width = dragViewSize.x - margin; - int height = dragViewSize.y - margin; - if (width <= 0 || height <= 0) { - return null; - } - final Bitmap badge = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); // Create the actual drawable on the UI thread to avoid race conditions with // FolderIcon draw pass try { return MAIN_EXECUTOR.submit(() -> { FolderIcon icon = launcher.findFolderIcon(folderId); - return icon == null ? null : createDrawableOnUiThread(icon, badge, dragViewSize); + return icon == null ? null : createDrawableOnUiThread(icon, dragViewSize); + }).get(); } catch (Exception e) { Log.e(TAG, "Unable to create folder icon", e); @@ -96,49 +87,50 @@ public class FolderAdaptiveIcon extends AdaptiveIconDrawable { } } - /** - * Initializes various bitmaps on the UI thread and returns the final drawable. - */ private static FolderAdaptiveIcon createDrawableOnUiThread(FolderIcon icon, - Bitmap badgeBitmap, Point dragViewSize) { + Point dragViewSize) { Preconditions.assertUIThread(); - float margin = icon.getResources().getDimension(R.dimen.blur_size_medium_outline) / 2; - Canvas c = new Canvas(); + icon.getPreviewBounds(sTmpRect); + PreviewBackground bg = icon.getFolderBackground(); - // Initialize badge - c.setBitmap(badgeBitmap); - bg.drawShadow(c); - bg.drawBackgroundStroke(c); - icon.drawDot(c); + // assume square + assert (dragViewSize.x == dragViewSize.y); + final int previewSize = sTmpRect.width(); - // Initialize preview - final float sizeScaleFactor = 1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction(); - final int previewWidth = (int) (dragViewSize.x * sizeScaleFactor); - final int previewHeight = (int) (dragViewSize.y * sizeScaleFactor); + final int margin = (dragViewSize.x - previewSize) / 2; + final float previewShiftX = -sTmpRect.left + margin; + final float previewShiftY = -sTmpRect.top + margin; - final float shiftFactor = AdaptiveIconDrawable.getExtraInsetFraction() / sizeScaleFactor; - final float previewShiftX = shiftFactor * previewWidth; - final float previewShiftY = shiftFactor * previewHeight; - - Bitmap previewBitmap = BitmapRenderer.createHardwareBitmap(previewWidth, previewHeight, + // Initialize badge, which consists of the outline stroke, shadow and dot; these + // must be rendered above the foreground + Bitmap badgeBmp = BitmapRenderer.createHardwareBitmap(dragViewSize.x, dragViewSize.y, (canvas) -> { - int count = canvas.save(); + canvas.save(); canvas.translate(previewShiftX, previewShiftY); - icon.getPreviewItemManager().draw(canvas); - canvas.restoreToCount(count); + bg.drawShadow(canvas); + bg.drawBackgroundStroke(canvas); + icon.drawDot(canvas); + canvas.restore(); }); // Initialize mask Path mask = new Path(); Matrix m = new Matrix(); - m.setTranslate(margin, margin); + m.setTranslate(previewShiftX, previewShiftY); bg.getClipPath().transform(m, mask); - ShiftedBitmapDrawable badge = new ShiftedBitmapDrawable(badgeBitmap, margin, margin); - ShiftedBitmapDrawable foreground = new ShiftedBitmapDrawable(previewBitmap, - margin - previewShiftX, margin - previewShiftY); + Bitmap previewBitmap = BitmapRenderer.createHardwareBitmap(dragViewSize.x, dragViewSize.y, + (canvas) -> { + canvas.save(); + canvas.translate(previewShiftX, previewShiftY); + icon.getPreviewItemManager().draw(canvas); + canvas.restore(); + }); + + ShiftedBitmapDrawable badge = new ShiftedBitmapDrawable(badgeBmp, 0, 0); + ShiftedBitmapDrawable foreground = new ShiftedBitmapDrawable(previewBitmap, 0, 0); return new FolderAdaptiveIcon(new ColorDrawable(bg.getBgColor()), foreground, badge, mask); } diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index ab1ff102c6..f0d18ae63c 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -63,6 +63,7 @@ import com.android.launcher3.dot.FolderDotInfo; import com.android.launcher3.dragndrop.BaseItemDragListener; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragView; +import com.android.launcher3.dragndrop.DraggableView; import com.android.launcher3.icons.DotRenderer; import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.util.Executors; @@ -78,7 +79,8 @@ import java.util.function.Predicate; /** * An icon that can appear on in the workspace representing an {@link Folder}. */ -public class FolderIcon extends FrameLayout implements FolderListener, IconLabelDotView { +public class FolderIcon extends FrameLayout implements FolderListener, IconLabelDotView, + DraggableView { @Thunk ActivityContext mActivity; @Thunk Folder mFolder; @@ -230,6 +232,16 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel mBackground.getBounds(outBounds); } + @Override + public int getViewType() { + return DRAGGABLE_ICON; + } + + @Override + public void getVisualDragBounds(Rect bounds) { + getPreviewBounds(bounds); + } + public float getBackgroundStrokeWidth() { return mBackground.getStrokeWidth(); } @@ -525,6 +537,10 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel invalidate(); } + public boolean getIconVisible() { + return mBackgroundIsVisible; + } + public PreviewBackground getFolderBackground() { return mBackground; } diff --git a/src/com/android/launcher3/graphics/DragPreviewProvider.java b/src/com/android/launcher3/graphics/DragPreviewProvider.java index 94d30f69c3..ed9dfbbd79 100644 --- a/src/com/android/launcher3/graphics/DragPreviewProvider.java +++ b/src/com/android/launcher3/graphics/DragPreviewProvider.java @@ -30,14 +30,12 @@ import android.graphics.drawable.Drawable; import android.view.View; import com.android.launcher3.BubbleTextView; -import com.android.launcher3.FastBitmapDrawable; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.config.FeatureFlags; -import com.android.launcher3.folder.FolderIcon; +import com.android.launcher3.dragndrop.DraggableView; import com.android.launcher3.icons.BitmapRenderer; import com.android.launcher3.widget.LauncherAppWidgetHostView; -import com.android.launcher3.widget.PendingAppWidgetHostView; import java.nio.ByteBuffer; @@ -53,7 +51,7 @@ public class DragPreviewProvider { // The padding added to the drag view during the preview generation. public final int previewPadding; - protected final int blurSizeOutline; + public final int blurSizeOutline; private OutlineGeneratorCallback mOutlineGeneratorCallback; public Bitmap generatedDragOutline; @@ -66,56 +64,25 @@ public class DragPreviewProvider { mView = view; blurSizeOutline = context.getResources().getDimensionPixelSize(R.dimen.blur_size_medium_outline); - - if (mView instanceof BubbleTextView) { - Drawable d = ((BubbleTextView) mView).getIcon(); - Rect bounds = getDrawableBounds(d); - previewPadding = blurSizeOutline - bounds.left - bounds.top; - } else { - previewPadding = blurSizeOutline; - } + previewPadding = blurSizeOutline; } /** * Draws the {@link #mView} into the given {@param destCanvas}. */ protected void drawDragView(Canvas destCanvas, float scale) { - destCanvas.save(); + int saveCount = destCanvas.save(); destCanvas.scale(scale, scale); - if (mView instanceof BubbleTextView) { - Drawable d = ((BubbleTextView) mView).getIcon(); - Rect bounds = getDrawableBounds(d); - destCanvas.translate(blurSizeOutline / 2 - bounds.left, - blurSizeOutline / 2 - bounds.top); - if (d instanceof FastBitmapDrawable) { - ((FastBitmapDrawable) d).setScale(1); - } - d.draw(destCanvas); - } else { - final Rect clipRect = mTempRect; - mView.getDrawingRect(clipRect); - - boolean textVisible = false; - if (mView instanceof FolderIcon) { - // For FolderIcons the text can bleed into the icon area, and so we need to - // hide the text completely (which can't be achieved by clipping). - if (((FolderIcon) mView).getTextVisible()) { - ((FolderIcon) mView).setTextVisible(false); - textVisible = true; - } - } - destCanvas.translate(-mView.getScrollX() + blurSizeOutline / 2, - -mView.getScrollY() + blurSizeOutline / 2); - destCanvas.clipRect(clipRect); + if (mView instanceof DraggableView) { + DraggableView dv = (DraggableView) mView; + dv.prepareDrawDragView(); + dv.getVisualDragBounds(mTempRect); + destCanvas.translate(blurSizeOutline / 2 - mTempRect.left, + blurSizeOutline / 2 - mTempRect.top); mView.draw(destCanvas); - - // Restore text visibility of FolderIcon if necessary - if (textVisible) { - ((FolderIcon) mView).setTextVisible(true); - } } - destCanvas.restore(); + destCanvas.restoreToCount(saveCount); } /** @@ -123,28 +90,15 @@ public class DragPreviewProvider { * Responsibility for the bitmap is transferred to the caller. */ public Bitmap createDragBitmap() { - int width = mView.getWidth(); - int height = mView.getHeight(); - - if (mView instanceof BubbleTextView) { - Drawable d = ((BubbleTextView) mView).getIcon(); - Rect bounds = getDrawableBounds(d); - width = bounds.width(); - height = bounds.height(); - } else if (mView instanceof LauncherAppWidgetHostView) { - float scale = ((LauncherAppWidgetHostView) mView).getScaleToFit(); - width = (int) (mView.getWidth() * scale); - height = (int) (mView.getHeight() * scale); - - if (mView instanceof PendingAppWidgetHostView) { - // Use hardware renderer as the icon for the pending app widget may be a hw bitmap - return BitmapRenderer.createHardwareBitmap(width + blurSizeOutline, - height + blurSizeOutline, (c) -> drawDragView(c, scale)); - } else { - // Use software renderer for widgets as we know that they already work - return BitmapRenderer.createSoftwareBitmap(width + blurSizeOutline, - height + blurSizeOutline, (c) -> drawDragView(c, scale)); - } + int width = 0; + int height = 0; + if (mView instanceof DraggableView) { + ((DraggableView) mView).getVisualDragBounds(mTempRect); + width = mTempRect.width(); + height = mTempRect.height(); + } else { + width = mView.getWidth(); + height = mView.getHeight(); } return BitmapRenderer.createHardwareBitmap(width + blurSizeOutline, diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java index 5af5ebb4f5..9bac259efe 100644 --- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java +++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java @@ -59,6 +59,7 @@ import com.android.launcher3.dot.DotInfo; import com.android.launcher3.dragndrop.DragController; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.dragndrop.DragView; +import com.android.launcher3.dragndrop.DraggableView; import com.android.launcher3.notification.NotificationInfo; import com.android.launcher3.notification.NotificationItemView; import com.android.launcher3.notification.NotificationKeyData; @@ -662,7 +663,8 @@ public class PopupContainerWithArrow extends Arr iconShift.x = mIconLastTouchPos.x - sv.getIconCenter().x; iconShift.y = mIconLastTouchPos.y - mLauncher.getDeviceProfile().iconSizePx; - DragView dv = mLauncher.getWorkspace().beginDragShared(sv.getIconView(), + DraggableView draggableView = DraggableView.ofType(DraggableView.DRAGGABLE_ICON); + DragView dv = mLauncher.getWorkspace().beginDragShared(sv.getIconView(), draggableView, mContainer, sv.getFinalInfo(), new ShortcutDragPreviewProvider(sv.getIconView(), iconShift), new DragOptions()); diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java index fa625ed930..d41bb86949 100644 --- a/src/com/android/launcher3/views/FloatingIconView.java +++ b/src/com/android/launcher3/views/FloatingIconView.java @@ -67,7 +67,6 @@ import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.FolderAdaptiveIcon; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.graphics.IconShape; -import com.android.launcher3.graphics.ShiftedBitmapDrawable; import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.shortcuts.DeepShortcutView; @@ -412,9 +411,8 @@ public class FloatingIconView extends View implements drawable = originalView.getBackground(); } } else { - boolean isFolderIcon = originalView instanceof FolderIcon; - int width = isFolderIcon ? originalView.getWidth() : (int) pos.width(); - int height = isFolderIcon ? originalView.getHeight() : (int) pos.height(); + int width = (int) pos.width(); + int height = (int) pos.height(); if (supportsAdaptiveIcons) { drawable = getFullDrawable(l, info, width, height, sTmpObjArray); if (drawable instanceof AdaptiveIconDrawable) { @@ -499,20 +497,7 @@ public class FloatingIconView extends View implements } } - if (isFolderIcon) { - ((FolderIcon) originalView).getPreviewBounds(sTmpRect); - float bgStroke = ((FolderIcon) originalView).getBackgroundStrokeWidth(); - if (mForeground instanceof ShiftedBitmapDrawable) { - ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mForeground; - sbd.setShiftX(sbd.getShiftX() - sTmpRect.left - bgStroke); - sbd.setShiftY(sbd.getShiftY() - sTmpRect.top - bgStroke); - } - if (mBadge instanceof ShiftedBitmapDrawable) { - ShiftedBitmapDrawable sbd = (ShiftedBitmapDrawable) mBadge; - sbd.setShiftX(sbd.getShiftX() - sTmpRect.left - bgStroke); - sbd.setShiftY(sbd.getShiftY() - sTmpRect.top - bgStroke); - } - } else { + if (!isFolderIcon) { Utilities.scaleRectAboutCenter(mStartRevealRect, IconShape.getNormalizationScale()); } @@ -615,8 +600,9 @@ public class FloatingIconView extends View implements @WorkerThread @SuppressWarnings("WrongThread") private static int getOffsetForIconBounds(Launcher l, Drawable drawable, RectF position) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O || - !(drawable instanceof AdaptiveIconDrawable)) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O + || !(drawable instanceof AdaptiveIconDrawable) + || (drawable instanceof FolderAdaptiveIcon)) { return 0; } int blurSizeOutline = diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java index f3fd7ca4da..c1310e38fb 100644 --- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java +++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java @@ -20,6 +20,7 @@ import android.appwidget.AppWidgetProviderInfo; import android.content.Context; import android.content.res.Configuration; import android.graphics.PointF; +import android.graphics.Rect; import android.os.Handler; import android.os.SystemClock; import android.util.SparseBooleanArray; @@ -44,6 +45,7 @@ import com.android.launcher3.SimpleOnStylusPressListener; import com.android.launcher3.StylusEventHelper; import com.android.launcher3.Utilities; import com.android.launcher3.dragndrop.DragLayer; +import com.android.launcher3.dragndrop.DraggableView; import com.android.launcher3.util.Executors; import com.android.launcher3.util.Themes; import com.android.launcher3.views.BaseDragLayer.TouchCompleteListener; @@ -52,7 +54,7 @@ import com.android.launcher3.views.BaseDragLayer.TouchCompleteListener; * {@inheritDoc} */ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView - implements TouchCompleteListener, View.OnLongClickListener { + implements TouchCompleteListener, View.OnLongClickListener, DraggableView { // Related to the auto-advancing of widgets private static final long ADVANCE_INTERVAL = 20000; @@ -412,4 +414,18 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView } return false; } + + @Override + public int getViewType() { + return DRAGGABLE_WIDGET; + } + + @Override + public void getVisualDragBounds(Rect bounds) { + int x = (int) (1 - getScaleToFit()) * getMeasuredWidth() / 2; + int y = (int) (1 - getScaleToFit()) * getMeasuredWidth() / 2; + int width = (int) getScaleToFit() * getMeasuredWidth(); + int height = (int) getScaleToFit() * getMeasuredHeight(); + bounds.set(x, y , x + width, y + height); + } } diff --git a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java index 68b1595eed..104ad779d6 100644 --- a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java +++ b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java @@ -24,12 +24,15 @@ import android.view.View; import android.view.ViewDebug; import android.view.ViewGroup; +import com.android.launcher3.dragndrop.DraggableView; + import java.util.ArrayList; /** * Extension of AppWidgetHostView with support for controlled keyboard navigation. */ -public abstract class NavigableAppWidgetHostView extends AppWidgetHostView { +public abstract class NavigableAppWidgetHostView extends AppWidgetHostView + implements DraggableView { @ViewDebug.ExportedProperty(category = "launcher") private boolean mChildrenFocused; @@ -133,4 +136,14 @@ public abstract class NavigableAppWidgetHostView extends AppWidgetHostView { // The host view's background changes when selected, to indicate the focus is inside. setSelected(childIsFocused); } + + @Override + public int getViewType() { + return DRAGGABLE_WIDGET; + } + + @Override + public void getVisualDragBounds(Rect bounds) { + bounds.set(0, 0 , getMeasuredWidth(), getMeasuredHeight()); + } } diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java index 662e627d99..3c112740cf 100644 --- a/src/com/android/launcher3/widget/PendingItemDragHelper.java +++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java @@ -32,6 +32,7 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.PendingAddItemInfo; import com.android.launcher3.R; import com.android.launcher3.dragndrop.DragOptions; +import com.android.launcher3.dragndrop.DraggableView; import com.android.launcher3.dragndrop.LivePreviewWidgetCell; import com.android.launcher3.graphics.DragPreviewProvider; import com.android.launcher3.icons.LauncherIcons; @@ -79,6 +80,8 @@ public class PendingItemDragHelper extends DragPreviewProvider { mEstimatedCellSize = launcher.getWorkspace().estimateItemSize(mAddInfo); + DraggableView draggableView; + if (mAddInfo instanceof PendingAddWidgetInfo) { PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) mAddInfo; @@ -110,6 +113,7 @@ public class PendingItemDragHelper extends DragPreviewProvider { dragOffset = null; dragRegion = null; + draggableView = DraggableView.ofType(DraggableView.DRAGGABLE_WIDGET); } else { PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) mAddInfo; Drawable icon = createShortcutInfo.activityInfo.getFullResIcon(app.getIconCache()); @@ -136,6 +140,7 @@ public class PendingItemDragHelper extends DragPreviewProvider { dragRegion.top = (mEstimatedCellSize[1] - iconSize - dp.iconTextSizePx - dp.iconDrawablePaddingPx) / 2; dragRegion.bottom = dragRegion.top + iconSize; + draggableView = DraggableView.ofType(DraggableView.DRAGGABLE_ICON); } // Since we are not going through the workspace for starting the drag, set drag related @@ -148,8 +153,8 @@ public class PendingItemDragHelper extends DragPreviewProvider { + (int) ((scale * preview.getHeight() - preview.getHeight()) / 2); // Start the drag - launcher.getDragController().startDrag(preview, dragLayerX, dragLayerY, source, mAddInfo, - dragOffset, dragRegion, scale, scale, options); + launcher.getDragController().startDrag(preview, draggableView, dragLayerX, dragLayerY, + source, mAddInfo, dragOffset, dragRegion, scale, scale, options); } @Override