Update reorder and folder creation radii
- Before, dragging anywhere in the cell (including space between cells) would trigger a reorder. Now, we compute the radius to the closest cell edge
- For creating folders on icons, we split the difference between the reorder circle (above) and the icon size
Test: enable DEBUG_VISUALIZE_OCCUPIED and manually drag to ensure works as described above
Bug: 204406063
Change-Id: I368714634ed42a930fd16849f2bde1589df1aa63
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index c9befe8..adb1613 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -20,6 +20,7 @@
import static com.android.launcher3.anim.Interpolators.DEACCEL_1_5;
import static com.android.launcher3.dragndrop.DraggableView.DRAGGABLE_ICON;
+import static com.android.launcher3.icons.IconNormalizer.ICON_VISIBLE_AREA_FACTOR;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -446,6 +447,7 @@
Rect cellBounds = new Rect();
// Will contain the bounds of the cell including spacing between cells.
Rect cellBoundsWithSpacing = new Rect();
+ int[] targetCell = new int[2];
int[] cellCenter = new int[2];
Paint debugPaint = new Paint();
debugPaint.setStrokeWidth(Utilities.dpToPx(1));
@@ -454,10 +456,10 @@
if (!mOccupied.cells[x][y]) {
continue;
}
- View child = getChildAt(x, y);
- boolean canCreateFolder = child instanceof DraggableView
- && ((DraggableView) child).getViewType() == DRAGGABLE_ICON;
+ targetCell[0] = x;
+ targetCell[1] = y;
+ boolean canCreateFolder = canCreateFolder(getChildAt(x, y));
cellToRect(x, y, 1, 1, cellBounds);
cellBoundsWithSpacing.set(cellBounds);
cellBoundsWithSpacing.inset(-mBorderSpace.x / 2, -mBorderSpace.y / 2);
@@ -468,13 +470,14 @@
// Draw reorder drag target.
debugPaint.setColor(Color.RED);
- canvas.drawRect(cellBoundsWithSpacing, debugPaint);
+ canvas.drawCircle(cellCenter[0], cellCenter[1], getReorderRadius(targetCell),
+ debugPaint);
// Draw folder creation drag target.
if (canCreateFolder) {
debugPaint.setColor(Color.GREEN);
canvas.drawCircle(cellCenter[0], cellCenter[1],
- getFolderCreationRadius(), debugPaint);
+ getFolderCreationRadius(targetCell), debugPaint);
}
canvas.restore();
@@ -506,6 +509,14 @@
}
/**
+ * Returns whether dropping an icon on the given View can create (or add to) a folder.
+ */
+ private boolean canCreateFolder(View child) {
+ return child instanceof DraggableView
+ && ((DraggableView) child).getViewType() == DRAGGABLE_ICON;
+ }
+
+ /**
* Indicates the progress of the Workspace entering the SpringLoaded state; allows the
* CellLayout to update various visuals for this state.
*
@@ -881,9 +892,36 @@
/**
* Returns the max distance from the center of a cell that can accept a drop to create a folder.
*/
- public float getFolderCreationRadius() {
+ public float getFolderCreationRadius(int[] targetCell) {
DeviceProfile grid = mActivity.getDeviceProfile();
- return grid.isTablet ? 0.75f * grid.iconSizePx : 0.55f * grid.iconSizePx;
+ float iconVisibleRadius = ICON_VISIBLE_AREA_FACTOR * grid.iconSizePx / 2;
+ // Halfway between reorder radius and icon.
+ return (getReorderRadius(targetCell) + iconVisibleRadius) / 2;
+ }
+
+ /**
+ * Returns the max distance from the center of a cell that will start to reorder on drag over.
+ */
+ public float getReorderRadius(int[] targetCell) {
+ int[] centerPoint = mTmpPoint;
+ getWorkspaceCellVisualCenter(targetCell[0], targetCell[1], centerPoint);
+
+ Rect cellBoundsWithSpacing = mTempRect;
+ cellToRect(targetCell[0], targetCell[1], 1, 1, cellBoundsWithSpacing);
+ cellBoundsWithSpacing.inset(-mBorderSpace.x / 2, -mBorderSpace.y / 2);
+
+ if (canCreateFolder(getChildAt(targetCell[0], targetCell[1]))) {
+ // Take only the circle in the smaller dimension, to ensure we don't start reordering
+ // too soon before accepting a folder drop.
+ int minRadius = centerPoint[0] - cellBoundsWithSpacing.left;
+ minRadius = Math.min(minRadius, centerPoint[1] - cellBoundsWithSpacing.top);
+ minRadius = Math.min(minRadius, cellBoundsWithSpacing.right - centerPoint[0]);
+ minRadius = Math.min(minRadius, cellBoundsWithSpacing.bottom - centerPoint[1]);
+ return minRadius;
+ }
+ // Take up the entire cell, including space between this cell and the adjacent ones.
+ return (float) Math.hypot(cellBoundsWithSpacing.width() / 2f,
+ cellBoundsWithSpacing.height() / 2f);
}
public int getCellWidth() {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 2345f51..00c8d8e 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1786,7 +1786,7 @@
boolean willCreateUserFolder(ItemInfo info, CellLayout target, int[] targetCell,
float distance, boolean considerTimeout) {
- if (distance > target.getFolderCreationRadius()) return false;
+ if (distance > target.getFolderCreationRadius(targetCell)) return false;
View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
return willCreateUserFolder(info, dropOverView, considerTimeout);
}
@@ -1821,7 +1821,7 @@
boolean willAddToExistingUserFolder(ItemInfo dragInfo, CellLayout target, int[] targetCell,
float distance) {
- if (distance > target.getFolderCreationRadius()) return false;
+ if (distance > target.getFolderCreationRadius(targetCell)) return false;
View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
return willAddToExistingUserFolder(dragInfo, dropOverView);
@@ -1845,7 +1845,7 @@
boolean createUserFolderIfNecessary(View newView, int container, CellLayout target,
int[] targetCell, float distance, boolean external, DragObject d) {
- if (distance > target.getFolderCreationRadius()) return false;
+ if (distance > target.getFolderCreationRadius(targetCell)) return false;
View v = target.getChildAt(targetCell[0], targetCell[1]);
boolean hasntMoved = false;
@@ -1902,7 +1902,7 @@
boolean addToExistingFolderIfNecessary(View newView, CellLayout target, int[] targetCell,
float distance, DragObject d, boolean external) {
- if (distance > target.getFolderCreationRadius()) return false;
+ if (distance > target.getFolderCreationRadius(targetCell)) return false;
View dropOverView = target.getChildAt(targetCell[0], targetCell[1]);
if (!mAddToExistingFolderOnDrop) return false;
@@ -2408,8 +2408,9 @@
mDragTargetLayout.visualizeDropLocation(mTargetCell[0], mTargetCell[1],
item.spanX, item.spanY, d);
} else if ((mDragMode == DRAG_MODE_NONE || mDragMode == DRAG_MODE_REORDER)
- && !mReorderAlarm.alarmPending() && (mLastReorderX != reorderX ||
- mLastReorderY != reorderY)) {
+ && !mReorderAlarm.alarmPending()
+ && (mLastReorderX != reorderX || mLastReorderY != reorderY)
+ && targetCellDistance < mDragTargetLayout.getReorderRadius(mTargetCell)) {
int[] resultSpan = new int[2];
mDragTargetLayout.performReorder((int) mDragViewVisualCenter[0],
@@ -2506,7 +2507,7 @@
}
private void manageFolderFeedback(float distance, DragObject dragObject) {
- if (distance > mDragTargetLayout.getFolderCreationRadius()) {
+ if (distance > mDragTargetLayout.getFolderCreationRadius(mTargetCell)) {
if ((mDragMode == DRAG_MODE_ADD_TO_FOLDER
|| mDragMode == DRAG_MODE_CREATE_FOLDER)) {
setDragMode(DRAG_MODE_NONE);