From e126d72fa8602e31fbb87d4b6e5d5ccac34a32d0 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Thu, 25 Feb 2021 10:45:20 -0500 Subject: [PATCH] More grid changes, closer to final specs. * Added isScalable, minCellWidth, minCellHeight, and borderSpacing attrs When isScalable is true, we use set workspace cell values to minCellWidth/minCellHeight and then scale the cell values to fit the available space. This allows us to have consistent aspect ratios when two devices match the display/grid options. This is different from the dynamic grid, which calculates cell values based on iconSize/textSize/etc and then allows the cell width to be as wide as space allows. I adjusted some variables so that they will auto adjust based on another value, indepenent from whether the grid isScalable or not. An example of this is the folder label text, where it's always set to be 1.14x of whatever the workspace icon text size is. This is so we don't need to add a bunch of more variables to DisplayOption/GridOption. Bug: 175329686 Test: - switching between device profiles, - testing folder open/close - testing in multiwindow - testing in landscape Change-Id: Ia469ae0d65b518469ef264b726db46f4a3210056 --- res/layout/folder_application.xml | 3 +- res/layout/user_folder_icon_normalized.xml | 10 +- res/values/attrs.xml | 8 + res/values/config.xml | 2 +- res/values/dimens.xml | 16 +- .../launcher3/AppWidgetResizeFrame.java | 33 ++-- src/com/android/launcher3/BubbleTextView.java | 3 +- src/com/android/launcher3/DeviceProfile.java | 146 ++++++++++++------ .../launcher3/InvariantDeviceProfile.java | 43 ++++++ src/com/android/launcher3/ResourceUtils.java | 8 +- src/com/android/launcher3/folder/Folder.java | 13 +- .../folder/FolderAnimationManager.java | 4 +- 12 files changed, 204 insertions(+), 85 deletions(-) diff --git a/res/layout/folder_application.xml b/res/layout/folder_application.xml index 32a5419b8e..1cdee08c25 100644 --- a/res/layout/folder_application.xml +++ b/res/layout/folder_application.xml @@ -21,4 +21,5 @@ android:textColor="?attr/folderTextColor" android:includeFontPadding="false" android:hapticFeedbackEnabled="false" - launcher:iconDisplay="folder" /> + launcher:iconDisplay="folder" + launcher:centerVertically="true" /> diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml index c230dadd8f..d38a77a623 100644 --- a/res/layout/user_folder_icon_normalized.xml +++ b/res/layout/user_folder_icon_normalized.xml @@ -27,15 +27,12 @@ android:clipToPadding="false" android:layout_width="match_parent" android:layout_height="match_parent" - android:paddingLeft="16dp" - android:paddingRight="16dp" - android:paddingTop="16dp" launcher:pageIndicator="@+id/folder_page_indicator" /> + android:textColorHint="?attr/folderHintColor"/> + + @@ -150,6 +152,12 @@ + + + + + + diff --git a/res/values/config.xml b/res/values/config.xml index 41d1a12059..89415b89a3 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -24,7 +24,7 @@ - 90 + 85 50 diff --git a/res/values/dimens.xml b/res/values/dimens.xml index acc6466caa..e532305599 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -20,6 +20,7 @@ 8dp + 8dp 7dp 8dp @@ -27,7 +28,6 @@ 16dp 5.5dp 8dp - 7dp 8dp @@ -37,6 +37,9 @@ 34dp 0dp + + 22dp + 24dp 1dp @@ -90,7 +93,6 @@ 2dp - 3dp 16dp @@ -148,10 +150,12 @@ 9dp 6dp - 13sp - 12dp - 12dp - 16sp + + 1.14 + 48dp + + 8dp + 16dp 24dp diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java index be92c5d133..4f008e26da 100644 --- a/src/com/android/launcher3/AppWidgetResizeFrame.java +++ b/src/com/android/launcher3/AppWidgetResizeFrame.java @@ -3,7 +3,6 @@ package com.android.launcher3; import static com.android.launcher3.LauncherAnimUtils.LAYOUT_HEIGHT; import static com.android.launcher3.LauncherAnimUtils.LAYOUT_WIDTH; import static com.android.launcher3.Utilities.ATLEAST_S; -import static com.android.launcher3.config.FeatureFlags.ENABLE_FOUR_COLUMNS; import static com.android.launcher3.views.BaseDragLayer.LAYOUT_X; import static com.android.launcher3.views.BaseDragLayer.LAYOUT_Y; @@ -50,6 +49,14 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O inv.portraitProfile.getCellSize()}; }); + // Represents the border spacing size on the grid in the two orientations. + public static final MainThreadInitializedObject BORDER_SPACING_SIZE = + new MainThreadInitializedObject<>(c -> { + InvariantDeviceProfile inv = LauncherAppState.getIDP(c); + return new int[] {inv.landscapeProfile.cellLayoutBorderSpacingPx, + inv.portraitProfile.cellLayoutBorderSpacingPx}; + }); + private static final int HANDLE_COUNT = 4; private static final int INDEX_LEFT = 0; private static final int INDEX_TOP = 1; @@ -370,16 +377,12 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O } } - private static PointF getWidgetSize(Context context, Point cellSize, int spanX, int spanY) { + private static PointF getWidgetSize(Context context, Point cellSize, int spanX, int spanY, + int borderSpacing) { final float density = context.getResources().getDisplayMetrics().density; - float hBorderSpacing = 0; - float vBorderSpacing = 0; - if (ENABLE_FOUR_COLUMNS.get()) { - final int borderSpacing = context.getResources() - .getDimensionPixelSize(R.dimen.dynamic_grid_cell_border_spacing); - hBorderSpacing = (spanX - 1) * borderSpacing; - vBorderSpacing = (spanY - 1) * borderSpacing; - } + final float hBorderSpacing = (spanX - 1) * borderSpacing; + final float vBorderSpacing = (spanY - 1) * borderSpacing; + PointF widgetSize = new PointF(); widgetSize.x = ((spanX * cellSize.x) + hBorderSpacing) / density; widgetSize.y = ((spanY * cellSize.y) + vBorderSpacing) / density; @@ -389,10 +392,11 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O /** Returns the actual widget size given its span. */ public static PointF getWidgetSize(Context context, int spanX, int spanY) { final Point[] cellSize = CELL_SIZE.get(context); + final int[] borderSpacing = BORDER_SPACING_SIZE.get(context); if (isLandscape(context)) { - return getWidgetSize(context, cellSize[0], spanX, spanY); + return getWidgetSize(context, cellSize[0], spanX, spanY, borderSpacing[0]); } - return getWidgetSize(context, cellSize[1], spanX, spanY); + return getWidgetSize(context, cellSize[1], spanX, spanY, borderSpacing[1]); } /** Returns true if the screen is in landscape mode. */ @@ -404,9 +408,10 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O /** Returns the list of sizes for a widget of given span, in dp. */ public static ArrayList getWidgetSizes(Context context, int spanX, int spanY) { final Point[] cellSize = CELL_SIZE.get(context); + final int[] borderSpacing = BORDER_SPACING_SIZE.get(context); - PointF landSize = getWidgetSize(context, cellSize[0], spanX, spanY); - PointF portSize = getWidgetSize(context, cellSize[1], spanX, spanY); + PointF landSize = getWidgetSize(context, cellSize[0], spanX, spanY, borderSpacing[0]); + PointF portSize = getWidgetSize(context, cellSize[1], spanX, spanY, borderSpacing[1]); ArrayList sizes = new ArrayList<>(2); sizes.add(landSize); diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index ee4d7ecb55..e0be6de793 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -17,7 +17,6 @@ package com.android.launcher3; import static com.android.launcher3.FastBitmapDrawable.newIcon; -import static com.android.launcher3.config.FeatureFlags.ENABLE_FOUR_COLUMNS; import static com.android.launcher3.graphics.IconShape.getShape; import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon; import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound; @@ -194,7 +193,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver, setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx); setCompoundDrawablePadding(grid.iconDrawablePaddingPx); defaultIconSize = grid.iconSizePx; - setCenterVertically(ENABLE_FOUR_COLUMNS.get()); + setCenterVertically(grid.isScalableGrid); } else if (mDisplay == DISPLAY_ALL_APPS) { setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx); setCompoundDrawablePadding(grid.allAppsIconDrawablePaddingPx); diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 634093c141..7a9f852960 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -16,7 +16,7 @@ package com.android.launcher3; -import static com.android.launcher3.config.FeatureFlags.ENABLE_FOUR_COLUMNS; +import static com.android.launcher3.ResourceUtils.pxFromDp; import android.content.Context; import android.content.res.Configuration; @@ -66,6 +66,8 @@ public class DeviceProfile { public final float aspectRatio; + public final boolean isScalableGrid; + /** * The maximum amount of left/right workspace padding as a percentage of the screen width. * To be clear, this means that up to 7% of the screen width can be used as left padding, and @@ -79,8 +81,10 @@ public class DeviceProfile { private static final int PORTRAIT_TABLET_LEFT_RIGHT_PADDING_MULTIPLIER = 4; // Workspace - public final int desiredWorkspaceLeftRightMarginPx; - public final int cellLayoutBorderSpacingPx; + public final int desiredWorkspaceLeftRightOriginalPx; + public int desiredWorkspaceLeftRightMarginPx; + public final int cellLayoutBorderSpacingOriginalPx; + public int cellLayoutBorderSpacingPx; public final int cellLayoutPaddingLeftRightPx; public final int cellLayoutBottomPaddingPx; public final int edgeMarginPx; @@ -102,13 +106,21 @@ public class DeviceProfile { public int cellWidthPx; public int cellHeightPx; - public int cellYPaddingPx; public int workspaceCellPaddingXPx; + public int cellYPaddingPx; + public int cellYPaddingOriginalPx; + // Folder + public float folderLabelTextScale; + public int folderLabelTextSizePx; public int folderIconSizePx; public int folderIconOffsetYPx; + // Folder content + public int folderContentPaddingLeftRight; + public int folderContentPaddingTop; + // Folder cell public int folderCellWidthPx; public int folderCellHeightPx; @@ -164,9 +176,12 @@ public class DeviceProfile { this.inv = inv; this.isLandscape = isLandscape; this.isMultiWindowMode = isMultiWindowMode; + this.transposeLayoutWithOrientation = transposeLayoutWithOrientation; windowX = windowPosition.x; windowY = windowPosition.y; + isScalableGrid = inv.isScalable && !isVerticalBarLayout() && !isMultiWindowMode; + // Determine sizes. widthPx = width; heightPx = height; @@ -193,8 +208,6 @@ public class DeviceProfile { boolean isTallDevice = Float.compare(aspectRatio, TALL_DEVICE_ASPECT_RATIO_THRESHOLD) >= 0; // Some more constants - this.transposeLayoutWithOrientation = transposeLayoutWithOrientation; - context = getContext(context, info, isVerticalBarLayout() ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT); @@ -217,16 +230,25 @@ public class DeviceProfile { availableHeightPx = nonFinalAvailableHeightPx; edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin); - desiredWorkspaceLeftRightMarginPx = isVerticalBarLayout() ? 0 : edgeMarginPx; - cellYPaddingPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_y); - cellLayoutBorderSpacingPx = isVerticalBarLayout() - || isMultiWindowMode - || !ENABLE_FOUR_COLUMNS.get() - ? 0 : res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_border_spacing); + desiredWorkspaceLeftRightMarginPx = isVerticalBarLayout() ? 0 : isScalableGrid + ? res.getDimensionPixelSize(R.dimen.scalable_grid_left_right_margin) + : res.getDimensionPixelSize(R.dimen.dynamic_grid_left_right_margin); + desiredWorkspaceLeftRightOriginalPx = desiredWorkspaceLeftRightMarginPx; + + folderLabelTextScale = res.getFloat(R.dimen.folder_label_text_scale); + folderContentPaddingLeftRight = + res.getDimensionPixelSize(R.dimen.folder_content_padding_left_right); + folderContentPaddingTop = res.getDimensionPixelSize(R.dimen.folder_content_padding_top); + + setCellLayoutBorderSpacing(pxFromDp(inv.borderSpacing, mInfo.metrics, 1f)); + cellLayoutBorderSpacingOriginalPx = cellLayoutBorderSpacingPx; + int cellLayoutPaddingLeftRightMultiplier = !isVerticalBarLayout() && isTablet ? PORTRAIT_TABLET_LEFT_RIGHT_PADDING_MULTIPLIER : 1; - int cellLayoutPadding = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_layout_padding); + int cellLayoutPadding = isScalableGrid + ? 0 + : res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_layout_padding); if (isLandscape) { cellLayoutPaddingLeftRightPx = 0; cellLayoutBottomPaddingPx = cellLayoutPadding; @@ -259,16 +281,16 @@ public class DeviceProfile { hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0; int hotseatExtraVerticalSize = res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size); - hotseatBarSizePx = ResourceUtils.pxFromDp(inv.iconSize, mInfo.metrics) + hotseatBarSizePx = pxFromDp(inv.iconSize, mInfo.metrics, 1f) + (isVerticalBarLayout() ? (hotseatBarSidePaddingStartPx + hotseatBarSidePaddingEndPx) : (hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx - + (ENABLE_FOUR_COLUMNS.get() ? 0 : hotseatExtraVerticalSize))); + + (isScalableGrid ? 0 : hotseatExtraVerticalSize))); // Calculate all of the remaining variables. int extraSpace = updateAvailableDimensions(res); // Now that we have all of the variables calculated, we can tune certain sizes. - if (ENABLE_FOUR_COLUMNS.get()) { + if (isScalableGrid) { DevicePadding padding = inv.devicePaddings.getDevicePadding(extraSpace); workspaceTopPadding = padding.getWorkspaceTopPadding(extraSpace); workspaceBottomPadding = padding.getWorkspaceBottomPadding(extraSpace); @@ -299,6 +321,17 @@ public class DeviceProfile { IconShape.DEFAULT_PATH_SIZE); } + private void setCellLayoutBorderSpacing(int borderSpacing) { + if (isScalableGrid) { + cellLayoutBorderSpacingPx = borderSpacing; + folderContentPaddingLeftRight = borderSpacing; + folderContentPaddingTop = borderSpacing; + } else { + cellLayoutBorderSpacingPx = 0; + } + } + + public Builder toBuilder(Context context) { Point size = new Point(availableWidthPx, availableHeightPx); return new Builder(context, inv, mInfo) @@ -380,20 +413,42 @@ public class DeviceProfile { private int updateAvailableDimensions(Resources res) { updateIconSize(1f, res); - // Check to see if the icons fit within the available height. If not, then scale down. - float usedHeight = (cellHeightPx * inv.numRows) - + (cellLayoutBorderSpacingPx * (inv.numRows - 1)); - int maxHeight = (availableHeightPx - getTotalWorkspacePadding().y); + Point workspacePadding = getTotalWorkspacePadding(); + + // Check to see if the icons fit within the available height. + float usedHeight = getCellLayoutHeight(); + final int maxHeight = availableHeightPx - workspacePadding.y; float extraHeight = Math.max(0, maxHeight - usedHeight); - if (usedHeight > maxHeight) { - float scale = maxHeight / usedHeight; - updateIconSize(scale, res); - extraHeight = 0; + float scaleY = maxHeight / usedHeight; + boolean shouldScale = scaleY < 1f; + + float scaleX = 1f; + if (isScalableGrid) { + // We scale to fit the cellWidth and cellHeight in the available space. + // The benefit of scalable grids is that we can get consistent aspect ratios between + // devices. + float usedWidth = (cellWidthPx * inv.numColumns) + + (cellLayoutBorderSpacingPx * (inv.numColumns - 1)) + + (desiredWorkspaceLeftRightMarginPx * 2); + // We do not subtract padding here, as we also scale the workspace padding if needed. + scaleX = availableWidthPx / usedWidth; + shouldScale = true; } + + if (shouldScale) { + float scale = Math.min(scaleX, scaleY); + updateIconSize(scale, res); + extraHeight = Math.max(0, maxHeight - getCellLayoutHeight()); + } + updateAvailableFolderCellDimensions(res); return Math.round(extraHeight); } + private int getCellLayoutHeight() { + return (cellHeightPx * inv.numRows) + (cellLayoutBorderSpacingPx * (inv.numRows - 1)); + } + /** * Updating the iconSize affects many aspects of the launcher layout, such as: iconSizePx, * iconTextSizePx, iconDrawablePaddingPx, cellWidth/Height, allApps* variants, @@ -403,17 +458,21 @@ public class DeviceProfile { // Workspace final boolean isVerticalLayout = isVerticalBarLayout(); float invIconSizeDp = isVerticalLayout ? inv.landscapeIconSize : inv.iconSize; - iconSizePx = Math.max(1, (int) (ResourceUtils.pxFromDp(invIconSizeDp, mInfo.metrics) - * scale)); - iconTextSizePx = (int) (Utilities.pxFromSp(inv.iconTextSize, mInfo.metrics) * scale); + iconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mInfo.metrics, scale)); + iconTextSizePx = pxFromDp(inv.iconTextSize, mInfo.metrics, scale); iconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * scale); - if (ENABLE_FOUR_COLUMNS.get()) { - cellHeightPx = iconSizePx + iconDrawablePaddingPx - + Utilities.calculateTextHeight(iconTextSizePx) - + (cellYPaddingPx * 2); + setCellLayoutBorderSpacing((int) (cellLayoutBorderSpacingOriginalPx * scale)); + + if (isScalableGrid) { + cellWidthPx = pxFromDp(inv.minCellWidth, mInfo.metrics, scale); + cellHeightPx = pxFromDp(inv.minCellHeight, mInfo.metrics, scale); + int cellContentHeight = iconSizePx + iconDrawablePaddingPx + + Utilities.calculateTextHeight(iconTextSizePx); + cellYPaddingPx = Math.max(0, cellHeightPx - cellContentHeight) / 2; + desiredWorkspaceLeftRightMarginPx = (int) (desiredWorkspaceLeftRightOriginalPx * scale); } else { - cellYPaddingPx = 0; + cellWidthPx = iconSizePx + iconDrawablePaddingPx; cellHeightPx = iconSizePx + iconDrawablePaddingPx + Utilities.calculateTextHeight(iconTextSizePx); int cellPaddingY = (getCellSize().y - cellHeightPx) / 2; @@ -426,11 +485,10 @@ public class DeviceProfile { iconDrawablePaddingPx = cellPaddingY; } } - cellWidthPx = iconSizePx + iconDrawablePaddingPx; // All apps if (allAppsHasDifferentNumColumns()) { - allAppsIconSizePx = ResourceUtils.pxFromDp(inv.allAppsIconSize, mInfo.metrics); + allAppsIconSizePx = pxFromDp(inv.allAppsIconSize, mInfo.metrics); allAppsIconTextSizePx = Utilities.pxFromSp(inv.allAppsIconTextSize, mInfo.metrics); allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx; // We use 4 below to ensure labels are closer to their corresponding icon. @@ -474,12 +532,10 @@ public class DeviceProfile { } private void updateAvailableFolderCellDimensions(Resources res) { - int folderBottomPanelSize = res.getDimensionPixelSize(R.dimen.folder_label_padding_top) - + res.getDimensionPixelSize(R.dimen.folder_label_padding_bottom) - + Utilities.calculateTextHeight(res.getDimension(R.dimen.folder_label_text_size)); - updateFolderCellSize(1f, res); + final int folderBottomPanelSize = res.getDimensionPixelSize(R.dimen.folder_label_height); + // Don't let the folder get too close to the edges of the screen. int folderMargin = edgeMarginPx * 2; Point totalWorkspacePadding = getTotalWorkspacePadding(); @@ -488,13 +544,14 @@ public class DeviceProfile { float contentUsedHeight = folderCellHeightPx * inv.numFolderRows + ((inv.numFolderRows - 1) * cellLayoutBorderSpacingPx); int contentMaxHeight = availableHeightPx - totalWorkspacePadding.y - folderBottomPanelSize - - folderMargin; + - folderMargin - folderContentPaddingTop; float scaleY = contentMaxHeight / contentUsedHeight; // Check if the icons fit within the available width. float contentUsedWidth = folderCellWidthPx * inv.numFolderColumns + ((inv.numFolderColumns - 1) * cellLayoutBorderSpacingPx); - int contentMaxWidth = availableWidthPx - totalWorkspacePadding.x - folderMargin; + int contentMaxWidth = availableWidthPx - totalWorkspacePadding.x - folderMargin + - folderContentPaddingLeftRight * 2; float scaleX = contentMaxWidth / contentUsedWidth; float scale = Math.min(scaleX, scaleY); @@ -504,9 +561,10 @@ public class DeviceProfile { } private void updateFolderCellSize(float scale, Resources res) { - folderChildIconSizePx = (int) (ResourceUtils.pxFromDp(inv.iconSize, mInfo.metrics) * scale); - folderChildTextSizePx = - (int) (res.getDimensionPixelSize(R.dimen.folder_child_text_size) * scale); + float invIconSizeDp = isVerticalBarLayout() ? inv.landscapeIconSize : inv.iconSize; + folderChildIconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mInfo.metrics, scale)); + folderChildTextSizePx = pxFromDp(inv.iconTextSize, mInfo.metrics, scale); + folderLabelTextSizePx = (int) (folderChildTextSizePx * folderLabelTextScale); int textHeight = Utilities.calculateTextHeight(folderChildTextSizePx); int cellPaddingX = (int) (res.getDimensionPixelSize(R.dimen.folder_cell_x_padding) * scale); @@ -588,7 +646,7 @@ public class DeviceProfile { } else { // Pad the top and bottom of the workspace with search/hotseat bar sizes padding.set(desiredWorkspaceLeftRightMarginPx, - workspaceTopPadding + edgeMarginPx, + workspaceTopPadding + (isScalableGrid ? 0 : edgeMarginPx), desiredWorkspaceLeftRightMarginPx, paddingBottom); } diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 2a08c50008..bb60557122 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -111,6 +111,10 @@ public class InvariantDeviceProfile { public float allAppsIconSize; public float allAppsIconTextSize; + public float minCellHeight; + public float minCellWidth; + public float borderSpacing; + private SparseArray mExtraAttrs; /** @@ -123,6 +127,11 @@ public class InvariantDeviceProfile { */ public int numAllAppsColumns; + /** + * Do not query directly. see {@link DeviceProfile#isScalableGrid}. + */ + protected boolean isScalable; + public String dbFile; public int defaultLayoutId; int demoModeLayoutId; @@ -154,6 +163,10 @@ public class InvariantDeviceProfile { iconTextSize = p.iconTextSize; numHotseatIcons = p.numHotseatIcons; numAllAppsColumns = p.numAllAppsColumns; + isScalable = p.isScalable; + minCellHeight = p.minCellHeight; + minCellWidth = p.minCellWidth; + borderSpacing = p.borderSpacing; dbFile = p.dbFile; allAppsIconSize = p.allAppsIconSize; allAppsIconTextSize = p.allAppsIconTextSize; @@ -213,6 +226,9 @@ public class InvariantDeviceProfile { result.landscapeIconSize = defaultDisplayOption.landscapeIconSize; result.allAppsIconSize = Math.min( defaultDisplayOption.allAppsIconSize, myDisplayOption.allAppsIconSize); + result.minCellHeight = defaultDisplayOption.minCellHeight; + result.minCellWidth = defaultDisplayOption.minCellWidth; + result.borderSpacing = defaultDisplayOption.borderSpacing; devicePaddings = new DevicePaddings(context); initGrid(context, myInfo, result); @@ -259,6 +275,7 @@ public class InvariantDeviceProfile { numFolderRows = closestProfile.numFolderRows; numFolderColumns = closestProfile.numFolderColumns; numAllAppsColumns = closestProfile.numAllAppsColumns; + isScalable = closestProfile.isScalable; mExtraAttrs = closestProfile.extraAttrs; @@ -269,6 +286,10 @@ public class InvariantDeviceProfile { iconTextSize = displayOption.iconTextSize; fillResIconDpi = getLauncherIconDensity(iconBitmapSize); + minCellHeight = displayOption.minCellHeight; + minCellWidth = displayOption.minCellWidth; + borderSpacing = displayOption.borderSpacing; + if (Utilities.isGridOptionsEnabled(context)) { allAppsIconSize = displayOption.allAppsIconSize; allAppsIconTextSize = displayOption.allAppsIconTextSize; @@ -589,6 +610,8 @@ public class InvariantDeviceProfile { private final int defaultLayoutId; private final int demoModeLayoutId; + private final boolean isScalable; + private final SparseArray extraAttrs; public GridOption(Context context, AttributeSet attrs) { @@ -612,6 +635,9 @@ public class InvariantDeviceProfile { numAllAppsColumns = a.getInt( R.styleable.GridDisplayOption_numAllAppsColumns, numColumns); + isScalable = a.getBoolean( + R.styleable.GridDisplayOption_isScalable, false); + a.recycle(); extraAttrs = Themes.createValueMap(context, attrs, @@ -626,6 +652,10 @@ public class InvariantDeviceProfile { private final float minHeightDps; private final boolean canBeDefault; + private float minCellHeight; + private float minCellWidth; + private float borderSpacing; + private float iconSize; private float iconTextSize; private float landscapeIconSize; @@ -643,6 +673,10 @@ public class InvariantDeviceProfile { canBeDefault = a.getBoolean( R.styleable.ProfileDisplayOption_canBeDefault, false); + minCellHeight = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightDps, 0); + minCellWidth = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthDps, 0); + borderSpacing = a.getFloat(R.styleable.ProfileDisplayOption_borderSpacingDps, 0); + iconSize = a.getFloat(R.styleable.ProfileDisplayOption_iconImageSize, 0); landscapeIconSize = a.getFloat(R.styleable.ProfileDisplayOption_landscapeIconSize, iconSize); @@ -664,6 +698,9 @@ public class InvariantDeviceProfile { minWidthDps = 0; minHeightDps = 0; canBeDefault = false; + minCellHeight = 0; + minCellWidth = 0; + borderSpacing = 0; } private DisplayOption multiply(float w) { @@ -672,6 +709,9 @@ public class InvariantDeviceProfile { allAppsIconSize *= w; iconTextSize *= w; allAppsIconTextSize *= w; + minCellHeight *= w; + minCellWidth *= w; + borderSpacing *= w; return this; } @@ -681,6 +721,9 @@ public class InvariantDeviceProfile { allAppsIconSize += p.allAppsIconSize; iconTextSize += p.iconTextSize; allAppsIconTextSize += p.allAppsIconTextSize; + minCellHeight += p.minCellHeight; + minCellWidth += p.minCellWidth; + borderSpacing += p.borderSpacing; return this; } } diff --git a/src/com/android/launcher3/ResourceUtils.java b/src/com/android/launcher3/ResourceUtils.java index f60e1f8137..ece123dc62 100644 --- a/src/com/android/launcher3/ResourceUtils.java +++ b/src/com/android/launcher3/ResourceUtils.java @@ -60,7 +60,11 @@ public class ResourceUtils { } public static int pxFromDp(float size, DisplayMetrics metrics) { - return size < 0 ? INVALID_RESOURCE_HANDLE : Math.round( - TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, metrics)); + return pxFromDp(size, metrics, 1f); + } + + public static int pxFromDp(float size, DisplayMetrics metrics, float scale) { + return size < 0 ? INVALID_RESOURCE_HANDLE : Math.round(scale + * TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, size, metrics)); } } diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 504b29e75a..bcb3a54ef3 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -44,6 +44,7 @@ import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; import android.util.Pair; +import android.util.TypedValue; import android.view.FocusFinder; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -246,11 +247,16 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo @Override protected void onFinishInflate() { super.onFinishInflate(); + final DeviceProfile dp = mLauncher.getDeviceProfile(); + final int paddingLeftRight = dp.folderContentPaddingLeftRight; + mContent = findViewById(R.id.folder_content); + mContent.setPadding(paddingLeftRight, dp.folderContentPaddingTop, paddingLeftRight, 0); mContent.setFolder(this); mPageIndicator = findViewById(R.id.folder_page_indicator); mFolderName = findViewById(R.id.folder_name); + mFolderName.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.folderLabelTextSizePx); mFolderName.setOnBackKeyListener(this); mFolderName.setOnFocusChangeListener(this); mFolderName.setOnEditorActionListener(this); @@ -262,12 +268,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo mFolderName.forceDisableSuggestions(true); mFooter = findViewById(R.id.folder_footer); - - // We find out how tall footer wants to be (it is set to wrap_content), so that - // we can allocate the appropriate amount of space for it. - int measureSpec = MeasureSpec.UNSPECIFIED; - mFooter.measure(measureSpec, measureSpec); - mFooterHeight = mFooter.getMeasuredHeight(); + mFooterHeight = getResources().getDimensionPixelSize(R.dimen.folder_label_height); if (Utilities.ATLEAST_R) { mFolderWindowInsetsAnimationCallback = diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java index 1cac31eb18..feb528c96f 100644 --- a/src/com/android/launcher3/folder/FolderAnimationManager.java +++ b/src/com/android/launcher3/folder/FolderAnimationManager.java @@ -324,7 +324,9 @@ public class FolderAnimationManager { final int previewPosX = (int) ((mTmpParams.transX - iconOffsetX + previewItemOffsetX) / folderScale); - final int previewPosY = (int) ((mTmpParams.transY + previewItemOffsetY) / folderScale); + final float paddingTop = btv.getPaddingTop() * iconScale; + final int previewPosY = (int) ((mTmpParams.transY + previewItemOffsetY - paddingTop) + / folderScale); final float xDistance = previewPosX - btvLp.x; final float yDistance = previewPosY - btvLp.y;