diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index edd44e3424..222c7d62cb 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static com.android.launcher3.ResourceUtils.pxFromDp; import static com.android.launcher3.Utilities.dpiFromPx; import static com.android.launcher3.Utilities.pxFromSp; +import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR; import static com.android.launcher3.util.WindowManagerCompat.MIN_TABLET_WIDTH; import android.annotation.SuppressLint; @@ -399,7 +400,8 @@ public class DeviceProfile { } private void updateHotseatIconSize(int hotseatIconSizePx) { - hotseatCellHeightPx = hotseatIconSizePx; + // Ensure there is enough space for folder icons, which have a slightly larger radius. + hotseatCellHeightPx = (int) Math.ceil(hotseatIconSizePx * ICON_OVERLAP_FACTOR); if (isVerticalBarLayout()) { hotseatBarSizePx = hotseatIconSizePx + hotseatBarSidePaddingStartPx + hotseatBarSidePaddingEndPx; @@ -478,7 +480,7 @@ public class DeviceProfile { if (workspaceCellPaddingY < iconTextHeight) { iconTextSizePx = 0; iconDrawablePaddingPx = 0; - cellHeightPx = iconSizePx; + cellHeightPx = (int) Math.ceil(iconSizePx * ICON_OVERLAP_FACTOR); autoResizeAllAppsCells(); } } @@ -565,7 +567,8 @@ public class DeviceProfile { desiredWorkspaceLeftRightMarginPx = (int) (desiredWorkspaceLeftRightOriginalPx * scale); } else { cellWidthPx = iconSizePx + iconDrawablePaddingPx; - cellHeightPx = iconSizePx + iconDrawablePaddingPx + cellHeightPx = (int) Math.ceil(iconSizePx * ICON_OVERLAP_FACTOR) + + iconDrawablePaddingPx + Utilities.calculateTextHeight(iconTextSizePx); int cellPaddingY = (getCellSize().y - cellHeightPx) / 2; if (iconDrawablePaddingPx > cellPaddingY && !isVerticalLayout @@ -824,9 +827,9 @@ public class DeviceProfile { ? workspacePadding.bottom : hotseatBarSizePx - hotseatCellHeightPx - hotseatQsbHeight; - if (isScalableGrid && qsbBottomMarginPx <= freeSpace) { - return qsbBottomMarginPx; - } else { + if (isScalableGrid) { + return Math.min(qsbBottomMarginPx, freeSpace); + } else { return (int) (freeSpace * QSB_CENTER_FACTOR) + (isTaskbarPresent ? taskbarSize : getInsets().bottom); } @@ -899,14 +902,16 @@ public class DeviceProfile { return isVerticalBarLayout(); } - public int getCellHeight(@ContainerType int containerType) { + public int getCellContentHeight(@ContainerType int containerType) { switch (containerType) { case CellLayout.WORKSPACE: return cellHeightPx; case CellLayout.FOLDER: return folderCellHeightPx; case CellLayout.HOTSEAT: - return hotseatCellHeightPx; + // The hotseat is the only container where the cell height is going to be + // different from the content within that cell. + return iconSizePx; default: // ?? return 0; diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java index dff8534a9d..bebbf4f622 100644 --- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java +++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java @@ -122,7 +122,7 @@ public class ShortcutAndWidgetContainer extends ViewGroup implements FolderIcon. public int getCellContentHeight() { return Math.min(getMeasuredHeight(), - mActivity.getDeviceProfile().getCellHeight(mContainerType)); + mActivity.getDeviceProfile().getCellContentHeight(mContainerType)); } public void measureChild(View child) { diff --git a/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java b/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java index 6a6603c9da..74d9a228e2 100644 --- a/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java +++ b/src/com/android/launcher3/dragndrop/FolderAdaptiveIcon.java @@ -21,11 +21,11 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import android.annotation.TargetApi; import android.graphics.Bitmap; import android.graphics.Matrix; +import android.graphics.Paint; 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; import android.os.Build; import android.util.Log; @@ -129,10 +129,19 @@ public class FolderAdaptiveIcon extends AdaptiveIconDrawable { canvas.restore(); }); + Bitmap bgBitmap = BitmapRenderer.createHardwareBitmap(dragViewSize.x, dragViewSize.y, + (canvas) -> { + Paint p = new Paint(); + p.setColor(bg.getBgColor()); + + canvas.drawCircle(dragViewSize.x / 2f, dragViewSize.y / 2f, bg.getRadius(), p); + }); + ShiftedBitmapDrawable badge = new ShiftedBitmapDrawable(badgeBmp, 0, 0); ShiftedBitmapDrawable foreground = new ShiftedBitmapDrawable(previewBitmap, 0, 0); + ShiftedBitmapDrawable background = new ShiftedBitmapDrawable(bgBitmap, 0, 0); - return new FolderAdaptiveIcon(new ColorDrawable(bg.getBgColor()), foreground, badge, mask); + return new FolderAdaptiveIcon(background, foreground, badge, mask); } @Override diff --git a/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java b/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java index 54967a9915..8cd91d3a43 100644 --- a/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java +++ b/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java @@ -7,7 +7,9 @@ public class ClippedFolderIconLayoutRule { private static final float MIN_SCALE = 0.44f; private static final float MAX_SCALE = 0.51f; - private static final float MAX_RADIUS_DILATION = 0.1f; + private static final float MAX_RADIUS_DILATION = 0.25f; + // The max amount of overlap the preview items can go outside of the background bounds. + public static final float ICON_OVERLAP_FACTOR = 1 + (MAX_RADIUS_DILATION / 2f); private static final float ITEM_RADIUS_SCALE_FACTOR = 1.15f; public static final int EXIT_INDEX = -2; diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index f005b61823..60d8cdbd7c 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -16,6 +16,7 @@ package com.android.launcher3.folder; +import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR; import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW; import static com.android.launcher3.folder.PreviewItemManager.INITIAL_ITEM_ANIMATION_DURATION; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_AUTO_LABELED; @@ -236,6 +237,8 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel public void getPreviewBounds(Rect outBounds) { mPreviewItemManager.recomputePreviewDrawingParams(); mBackground.getBounds(outBounds); + // The preview items go outside of the bounds of the background. + Utilities.scaleRectAboutCenter(outBounds, ICON_OVERLAP_FACTOR); } public float getBackgroundStrokeWidth() { diff --git a/src/com/android/launcher3/folder/PreviewBackground.java b/src/com/android/launcher3/folder/PreviewBackground.java index 460521f1a4..18d0b10528 100644 --- a/src/com/android/launcher3/folder/PreviewBackground.java +++ b/src/com/android/launcher3/folder/PreviewBackground.java @@ -16,6 +16,7 @@ package com.android.launcher3.folder; +import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR; import static com.android.launcher3.graphics.IconShape.getShape; import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound; @@ -186,7 +187,7 @@ public class PreviewBackground extends CellLayout.DelegatedCellDrawing { outBounds.set(left, top, right, bottom); } - int getRadius() { + public int getRadius() { return previewSize / 2; } @@ -348,7 +349,12 @@ public class PreviewBackground extends CellLayout.DelegatedCellDrawing { public Path getClipPath() { mPath.reset(); - getShape().addToPath(mPath, getOffsetX(), getOffsetY(), getScaledRadius()); + float radius = getScaledRadius() * ICON_OVERLAP_FACTOR; + // Find the difference in radius so that the clip path remains centered. + float radiusDifference = radius - getRadius(); + float offsetX = basePreviewOffsetX - radiusDifference; + float offsetY = basePreviewOffsetY - radiusDifference; + getShape().addToPath(mPath, offsetX, offsetY, radius); return mPath; }