Refactor / Cleanup / Simplify a bunch of dnd related rendering / animation
Addresses:
=> Fix folder icon drop location mapping (was very far off)
=> Fix BubbleTextView drop animation shifted by a few pixels
=> Get rid multiple unnecessary calls to setDragMode(none), was breaking
some of the reorder flow; still some issues to address here.
=> Fix folder icon parallax (didn't work when the folder had a dot)
Test: manual
Change-Id: I5959cf341996f75d30212353ec096ed25bf40ea5
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index e6f8a85..21a8fd4 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -46,6 +46,7 @@
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 @@
* 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 @@
private final ActivityContext mActivity;
private Drawable mIcon;
- private final boolean mCenterVertically;
+ private boolean mCenterVertically;
private final int mDisplay;
@@ -701,4 +702,24 @@
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 e3eb387..6c562cf 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -58,6 +58,7 @@
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 @@
@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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
this.child = child;
this.mode = mode;
+
+ // TODO issue!
setInitialAnimationValues(false);
finalScale = (mChildScale - (CHILD_DIVIDEND / child.getWidth())) * initScale;
finalDeltaX = initDeltaX;
@@ -2162,6 +2175,8 @@
*/
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 @@
setItemPlacementDirty(false);
} else {
beginOrAdjustReorderPreviewAnimations(swapSolution, dragView,
- REORDER_ANIMATION_DURATION, ReorderPreviewAnimation.MODE_PREVIEW);
+ ReorderPreviewAnimation.MODE_PREVIEW);
}
mShortcutsAndWidgets.requestLayout();
}
@@ -2326,7 +2341,7 @@
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 @@
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 a32fd12..43ec5a6 100644
--- a/src/com/android/launcher3/DropTarget.java
+++ b/src/com/android/launcher3/DropTarget.java
@@ -23,6 +23,7 @@
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 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 1bd8263..c07dd9d 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -145,38 +145,46 @@
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 ead6018..d551776 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -70,6 +70,7 @@
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.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 @@
+ "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 @@
}
}
+ // 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 @@
.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 @@
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 @@
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 @@
}
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 de7bc6d..ffaada1 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -140,6 +140,8 @@
*
* @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 @@
* @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 @@
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 369bf28..409a1d5 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.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.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 @@
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 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 0000000..df99902
--- /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 0bb3fba..ea1fbdb 100644
--- a/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
+++ b/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java
@@ -20,10 +20,10 @@
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 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 @@
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 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 @@
}
}
- /**
- * 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 ab1ff10..f0d18ae 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.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 @@
/**
* 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 @@
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 @@
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 94d30f6..ed9dfbb 100644
--- a/src/com/android/launcher3/graphics/DragPreviewProvider.java
+++ b/src/com/android/launcher3/graphics/DragPreviewProvider.java
@@ -30,14 +30,12 @@
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 @@
// 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 @@
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 @@
* 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 5af5ebb..9bac259 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.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 @@
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 fa625ed..d41bb86 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.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 @@
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 @@
}
}
- 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 @@
@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 f3fd7ca..c1310e3 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -20,6 +20,7 @@
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.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 @@
* {@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 @@
}
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 68b1595..104ad77 100644
--- a/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/NavigableAppWidgetHostView.java
@@ -24,12 +24,15 @@
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 @@
// 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 662e627..3c11274 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.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 @@
mEstimatedCellSize = launcher.getWorkspace().estimateItemSize(mAddInfo);
+ DraggableView draggableView;
+
if (mAddInfo instanceof PendingAddWidgetInfo) {
PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) mAddInfo;
@@ -110,6 +113,7 @@
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 @@
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 @@
+ (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