diff options
Diffstat (limited to 'src/com/android/launcher3/CellLayout.java')
-rw-r--r-- | src/com/android/launcher3/CellLayout.java | 203 |
1 files changed, 143 insertions, 60 deletions
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java index a6adfc4bf6..adb1613e9d 100644 --- a/src/com/android/launcher3/CellLayout.java +++ b/src/com/android/launcher3/CellLayout.java @@ -18,8 +18,9 @@ package com.android.launcher3; import static android.animation.ValueAnimator.areAnimatorsEnabled; -import static com.android.launcher3.Utilities.getBoundsForViewInDragLayer; 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; @@ -38,7 +39,6 @@ import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; -import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Parcelable; import android.util.ArrayMap; @@ -62,6 +62,7 @@ import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.dragndrop.DraggableView; import com.android.launcher3.folder.PreviewBackground; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.util.CellAndSpan; @@ -92,7 +93,7 @@ public class CellLayout extends ViewGroup { private int mFixedCellWidth; private int mFixedCellHeight; @ViewDebug.ExportedProperty(category = "launcher") - private final int mBorderSpacing; + private final Point mBorderSpace; @ViewDebug.ExportedProperty(category = "launcher") private int mCountX; @@ -237,9 +238,9 @@ public class CellLayout extends ViewGroup { mActivity = ActivityContext.lookupContext(context); DeviceProfile deviceProfile = mActivity.getDeviceProfile(); - mBorderSpacing = mContainerType == FOLDER - ? deviceProfile.folderCellLayoutBorderSpacingPx - : deviceProfile.cellLayoutBorderSpacingPx; + mBorderSpace = mContainerType == FOLDER + ? new Point(deviceProfile.folderCellLayoutBorderSpacePx) + : new Point(deviceProfile.cellLayoutBorderSpacePx); mCellWidth = mCellHeight = -1; mFixedCellWidth = mFixedCellHeight = -1; @@ -309,7 +310,7 @@ public class CellLayout extends ViewGroup { mShortcutsAndWidgets = new ShortcutAndWidgetContainer(context, mContainerType); mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mCountX, mCountY, - mBorderSpacing); + mBorderSpace); addView(mShortcutsAndWidgets); } @@ -369,7 +370,7 @@ public class CellLayout extends ViewGroup { mFixedCellWidth = mCellWidth = width; mFixedCellHeight = mCellHeight = height; mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mCountX, mCountY, - mBorderSpacing); + mBorderSpace); } public void setGridSize(int x, int y) { @@ -379,7 +380,7 @@ public class CellLayout extends ViewGroup { mTmpOccupied = new GridOccupancy(mCountX, mCountY); mTempRectStack.clear(); mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mCountX, mCountY, - mBorderSpacing); + mBorderSpace); requestLayout(); } @@ -443,18 +444,43 @@ public class CellLayout extends ViewGroup { } if (DEBUG_VISUALIZE_OCCUPIED) { - int[] pt = new int[2]; - ColorDrawable cd = new ColorDrawable(Color.RED); - cd.setBounds(0, 0, mCellWidth, mCellHeight); - for (int i = 0; i < mCountX; i++) { - for (int j = 0; j < mCountY; j++) { - if (mOccupied.cells[i][j]) { - cellToPoint(i, j, pt); - canvas.save(); - canvas.translate(pt[0], pt[1]); - cd.draw(canvas); - canvas.restore(); + 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)); + for (int x = 0; x < mCountX; x++) { + for (int y = 0; y < mCountY; y++) { + if (!mOccupied.cells[x][y]) { + continue; } + 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); + getWorkspaceCellVisualCenter(x, y, cellCenter); + + canvas.save(); + canvas.clipRect(cellBoundsWithSpacing); + + // Draw reorder drag target. + debugPaint.setColor(Color.RED); + 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(targetCell), debugPaint); + } + + canvas.restore(); } } } @@ -483,6 +509,14 @@ public class CellLayout extends ViewGroup { } /** + * 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. * @@ -542,9 +576,9 @@ public class CellLayout extends ViewGroup { if (mVisualizeCells) { for (int i = 0; i < mCountX; i++) { for (int j = 0; j < mCountY; j++) { - int transX = i * mCellWidth + (i * mBorderSpacing) + getPaddingLeft() + int transX = i * mCellWidth + (i * mBorderSpace.x) + getPaddingLeft() + paddingX; - int transY = j * mCellHeight + (j * mBorderSpacing) + getPaddingTop() + int transY = j * mCellHeight + (j * mBorderSpace.y) + getPaddingTop() + paddingY; mVisualizeGridRect.offsetTo(transX, transY); @@ -568,12 +602,12 @@ public class CellLayout extends ViewGroup { // TODO b/194414754 clean this up, reconcile with cellToRect mVisualizeGridRect.set(paddingX, paddingY, - mCellWidth * spanX + mBorderSpacing * (spanX - 1) - paddingX, - mCellHeight * spanY + mBorderSpacing * (spanY - 1) - paddingY); + mCellWidth * spanX + mBorderSpace.x * (spanX - 1) - paddingX, + mCellHeight * spanY + mBorderSpace.y * (spanY - 1) - paddingY); - int transX = x * mCellWidth + (x * mBorderSpacing) + int transX = x * mCellWidth + (x * mBorderSpace.x) + getPaddingLeft() + paddingX; - int transY = y * mCellHeight + (y * mBorderSpacing) + int transY = y * mCellHeight + (y * mBorderSpace.y) + getPaddingTop() + paddingY; mVisualizeGridRect.offsetTo(transX, transY); @@ -818,7 +852,7 @@ public class CellLayout extends ViewGroup { } /** - * Given a cell coordinate and span return the point that represents the center of the regio + * Given a cell coordinate and span return the point that represents the center of the region * * @param cellX X coordinate of the cell * @param cellY Y coordinate of the cell @@ -831,11 +865,65 @@ public class CellLayout extends ViewGroup { result[1] = mTempRect.centerY(); } - public float getDistanceFromCell(float x, float y, int[] cell) { - cellToCenterPoint(cell[0], cell[1], mTmpPoint); + /** + * Returns the distance between the given coordinate and the visual center of the given cell. + */ + public float getDistanceFromWorkspaceCellVisualCenter(float x, float y, int[] cell) { + getWorkspaceCellVisualCenter(cell[0], cell[1], mTmpPoint); return (float) Math.hypot(x - mTmpPoint[0], y - mTmpPoint[1]); } + private void getWorkspaceCellVisualCenter(int cellX, int cellY, int[] outPoint) { + View child = getChildAt(cellX, cellY); + if (child instanceof DraggableView) { + DraggableView draggableChild = (DraggableView) child; + if (draggableChild.getViewType() == DRAGGABLE_ICON) { + cellToPoint(cellX, cellY, outPoint); + draggableChild.getWorkspaceVisualDragBounds(mTempRect); + mTempRect.offset(outPoint[0], outPoint[1]); + outPoint[0] = mTempRect.centerX(); + outPoint[1] = mTempRect.centerY(); + return; + } + } + cellToCenterPoint(cellX, cellY, outPoint); + } + + /** + * Returns the max distance from the center of a cell that can accept a drop to create a folder. + */ + public float getFolderCreationRadius(int[] targetCell) { + DeviceProfile grid = mActivity.getDeviceProfile(); + 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() { return mCellWidth; } @@ -859,15 +947,15 @@ public class CellLayout extends ViewGroup { int childHeightSize = heightSize - (getPaddingTop() + getPaddingBottom()); if (mFixedCellWidth < 0 || mFixedCellHeight < 0) { - int cw = DeviceProfile.calculateCellWidth(childWidthSize, mBorderSpacing, + int cw = DeviceProfile.calculateCellWidth(childWidthSize, mBorderSpace.x, mCountX); - int ch = DeviceProfile.calculateCellHeight(childHeightSize, mBorderSpacing, + int ch = DeviceProfile.calculateCellHeight(childHeightSize, mBorderSpace.y, mCountY); if (cw != mCellWidth || ch != mCellHeight) { mCellWidth = cw; mCellHeight = ch; mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mCountX, mCountY, - mBorderSpacing); + mBorderSpace); } } @@ -921,7 +1009,7 @@ public class CellLayout extends ViewGroup { */ public int getUnusedHorizontalSpace() { return getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - (mCountX * mCellWidth) - - ((mCountX - 1) * mBorderSpacing); + - ((mCountX - 1) * mBorderSpace.x); } @Override @@ -1071,18 +1159,12 @@ public class CellLayout extends ViewGroup { // Apply local extracted color if the DragView is an AppWidgetHostViewDrawable. View view = dragObject.dragView.getContentView(); if (view instanceof LauncherAppWidgetHostView) { - Launcher launcher = Launcher.getLauncher(dragObject.dragView.getContext()); + Launcher launcher = Launcher.getLauncher(getContext()); Workspace workspace = launcher.getWorkspace(); int screenId = workspace.getIdForScreen(this); - int pageId = workspace.getPageIndexForScreenId(screenId); cellToRect(targetCell[0], targetCell[1], spanX, spanY, mTempRect); - // Now get the rect in drag layer coordinates. - getBoundsForViewInDragLayer(launcher.getDragLayer(), this, mTempRect, true, - mTmpFloatArray, mTempRectF); - Utilities.setRect(mTempRectF, mTempRect); - - ((LauncherAppWidgetHostView) view).handleDrag(mTempRect, pageId); + ((LauncherAppWidgetHostView) view).handleDrag(mTempRect, this, screenId); } } @@ -2148,7 +2230,7 @@ public class CellLayout extends ViewGroup { mShakeAnimators.clear(); } - private void commitTempPlacement() { + private void commitTempPlacement(View dragView) { mTmpOccupied.copyTo(mOccupied); int screenId = Launcher.cast(mActivity).getWorkspace().getIdForScreen(this); @@ -2166,7 +2248,7 @@ public class CellLayout extends ViewGroup { ItemInfo info = (ItemInfo) child.getTag(); // We do a null check here because the item info can be null in the case of the // AllApps button in the hotseat. - if (info != null) { + if (info != null && child != dragView) { final boolean requiresDbUpdate = (info.cellX != lp.tmpCellX || info.cellY != lp.tmpCellY || info.spanX != lp.cellHSpan || info.spanY != lp.cellVSpan); @@ -2328,7 +2410,7 @@ public class CellLayout extends ViewGroup { animateItemsToSolution(swapSolution, dragView, commit); if (commit) { - commitTempPlacement(); + commitTempPlacement(null); completeAndClearReorderPreviewAnimations(); setItemPlacementDirty(false); } else { @@ -2422,7 +2504,8 @@ public class CellLayout extends ViewGroup { if (!DESTRUCTIVE_REORDER && (mode == MODE_ON_DROP || mode == MODE_ON_DROP_EXTERNAL)) { - commitTempPlacement(); + // Since the temp solution didn't update dragView, don't commit it either + commitTempPlacement(dragView); completeAndClearReorderPreviewAnimations(); setItemPlacementDirty(false); } else { @@ -2598,11 +2681,11 @@ public class CellLayout extends ViewGroup { + (int) Math.ceil(getUnusedHorizontalSpace() / 2f); final int vStartPadding = getPaddingTop(); - int x = hStartPadding + (cellX * mBorderSpacing) + (cellX * cellWidth); - int y = vStartPadding + (cellY * mBorderSpacing) + (cellY * cellHeight); + int x = hStartPadding + (cellX * mBorderSpace.x) + (cellX * cellWidth); + int y = vStartPadding + (cellY * mBorderSpace.y) + (cellY * cellHeight); - int width = cellHSpan * cellWidth + ((cellHSpan - 1) * mBorderSpacing); - int height = cellVSpan * cellHeight + ((cellVSpan - 1) * mBorderSpacing); + int width = cellHSpan * cellWidth + ((cellHSpan - 1) * mBorderSpace.x); + int height = cellVSpan * cellHeight + ((cellVSpan - 1) * mBorderSpace.y); resultRect.set(x, y, x + width, y + height); } @@ -2621,12 +2704,12 @@ public class CellLayout extends ViewGroup { public int getDesiredWidth() { return getPaddingLeft() + getPaddingRight() + (mCountX * mCellWidth) - + ((mCountX - 1) * mBorderSpacing); + + ((mCountX - 1) * mBorderSpace.x); } public int getDesiredHeight() { return getPaddingTop() + getPaddingBottom() + (mCountY * mCellHeight) - + ((mCountY - 1) * mBorderSpacing); + + ((mCountY - 1) * mBorderSpace.y); } public boolean isOccupied(int x, int y) { @@ -2742,20 +2825,20 @@ public class CellLayout extends ViewGroup { } public void setup(int cellWidth, int cellHeight, boolean invertHorizontally, int colCount, - int rowCount, int borderSpacing, @Nullable Rect inset) { + int rowCount, Point borderSpace, @Nullable Rect inset) { setup(cellWidth, cellHeight, invertHorizontally, colCount, rowCount, 1.0f, 1.0f, - borderSpacing, inset); + borderSpace, inset); } /** - * Use this method, as opposed to {@link #setup(int, int, boolean, int, int, int, Rect)}, + * Use this method, as opposed to {@link #setup(int, int, boolean, int, int, Point, Rect)}, * if the view needs to be scaled. * * ie. In multi-window mode, we setup widgets so that they are measured and laid out * using their full/invariant device profile sizes. */ public void setup(int cellWidth, int cellHeight, boolean invertHorizontally, int colCount, - int rowCount, float cellScaleX, float cellScaleY, int borderSpacing, + int rowCount, float cellScaleX, float cellScaleY, Point borderSpace, @Nullable Rect inset) { if (isLockedToGrid) { final int myCellHSpan = cellHSpan; @@ -2767,16 +2850,16 @@ public class CellLayout extends ViewGroup { myCellX = colCount - myCellX - cellHSpan; } - int hBorderSpacing = (myCellHSpan - 1) * borderSpacing; - int vBorderSpacing = (myCellVSpan - 1) * borderSpacing; + int hBorderSpacing = (myCellHSpan - 1) * borderSpace.x; + int vBorderSpacing = (myCellVSpan - 1) * borderSpace.y; float myCellWidth = ((myCellHSpan * cellWidth) + hBorderSpacing) / cellScaleX; float myCellHeight = ((myCellVSpan * cellHeight) + vBorderSpacing) / cellScaleY; width = Math.round(myCellWidth) - leftMargin - rightMargin; height = Math.round(myCellHeight) - topMargin - bottomMargin; - x = leftMargin + (myCellX * cellWidth) + (myCellX * borderSpacing); - y = topMargin + (myCellY * cellHeight) + (myCellY * borderSpacing); + x = leftMargin + (myCellX * cellWidth) + (myCellX * borderSpace.x); + y = topMargin + (myCellY * cellHeight) + (myCellY * borderSpace.y); if (inset != null) { x -= inset.left; @@ -2878,7 +2961,7 @@ public class CellLayout extends ViewGroup { directionVector, null, false, configuration).isSolution) { if (commitConfig) { copySolutionToTempState(configuration, null); - commitTempPlacement(); + commitTempPlacement(null); // undo marking cells occupied since there is actually nothing being placed yet. mOccupied.markCells(0, mCountY - 1, mCountX, 1, false); } |