Loading res/values/config.xml +2 −0 Original line number Diff line number Diff line Loading @@ -242,6 +242,8 @@ <item>@dimen/iconSize72dp</item> </integer-array> <dimen name="minimum_icon_label_size">8sp</dimen> <!-- Used for custom widgets --> <array name="custom_widget_providers"/> </resources> src/com/android/launcher3/DeviceProfile.java +19 −20 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ import com.android.launcher3.responsive.FolderSpecs; import com.android.launcher3.responsive.HotseatSpecs; import com.android.launcher3.responsive.WorkspaceSpecs; import com.android.launcher3.uioverrides.ApiWrapper; import com.android.launcher3.util.CellContentDimensions; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.Info; import com.android.launcher3.util.IconSizeSteps; Loading Loading @@ -924,14 +925,11 @@ public class DeviceProfile { - iconTextHeight; if (mIsResponsiveGrid) { // Hide text only if doesn't fit inside the cell for responsive grid if (workspaceCellPaddingY < 0) { iconTextSizePx = 0; iconDrawablePaddingPx = 0; int iconSizeWithOverlap = getIconSizeWithOverlap(iconSizePx); cellYPaddingPx = Math.max(0, getCellSize().y - iconSizeWithOverlap) / 2; autoResizeAllAppsCells(); } return; } Loading Loading @@ -1047,22 +1045,23 @@ public class DeviceProfile { iconSizePx = mIconSizeSteps.getIconSmallerThan(cellWidthPx); } // TODO(b/296400197): isVerticalBar shouldn't show labels anymore iconDrawablePaddingPx = getNormalizedIconDrawablePadding(); int iconTextHeight = Utilities.calculateTextHeight(iconTextSizePx); int cellContentHeight = iconSizePx + iconDrawablePaddingPx + iconTextHeight; while (iconSizePx > mIconSizeSteps.minimumIconSize() && cellContentHeight > cellHeightPx) { iconDrawablePaddingPx -= cellContentHeight - cellHeightPx; if (iconDrawablePaddingPx < 0) { // get a smaller icon size iconSizePx = mIconSizeSteps.getNextLowerIconSize(iconSizePx); iconDrawablePaddingPx = getNormalizedIconDrawablePadding(); CellContentDimensions cellContentDimensions = new CellContentDimensions(iconSizePx, iconDrawablePaddingPx, iconTextSizePx); if (isVerticalLayout) { if (cellHeightPx < iconSizePx) { cellContentDimensions.setIconSizePx( mIconSizeSteps.getIconSmallerThan(cellHeightPx)); } // calculate new cellContentHeight cellContentHeight = iconSizePx + iconDrawablePaddingPx + iconTextHeight; } else { cellContentDimensions.resizeToFitCellHeight(cellHeightPx, mIconSizeSteps); } iconSizePx = cellContentDimensions.getIconSizePx(); iconDrawablePaddingPx = cellContentDimensions.getIconDrawablePaddingPx(); iconTextSizePx = cellContentDimensions.getIconTextSizePx(); int cellContentHeight = cellContentDimensions.getCellContentHeight(); cellYPaddingPx = Math.max(0, cellHeightPx - cellContentHeight) / 2; } else if (mIsScalableGrid) { Loading src/com/android/launcher3/util/CellContentDimensions.kt 0 → 100644 +69 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.util import com.android.launcher3.Utilities import kotlin.math.max class CellContentDimensions( var iconSizePx: Int, var iconDrawablePaddingPx: Int, var iconTextSizePx: Int ) { /** * This method goes through some steps to reduce the padding between icon and label, icon size * and then label size, until it can fit in the [cellHeightPx]. * * @return the height of the content after being sized down. */ fun resizeToFitCellHeight(cellHeightPx: Int, iconSizeSteps: IconSizeSteps): Int { var cellContentHeight = getCellContentHeight() // Step 1. Decrease drawable padding if (cellContentHeight > cellHeightPx) { val diff = cellContentHeight - cellHeightPx iconDrawablePaddingPx = max(0, iconDrawablePaddingPx - diff) cellContentHeight = getCellContentHeight() } while ( (iconTextSizePx > iconSizeSteps.minimumIconLabelSize || iconSizePx > iconSizeSteps.minimumIconSize()) && cellContentHeight > cellHeightPx ) { // Step 2. Decrease icon size iconSizePx = iconSizeSteps.getNextLowerIconSize(iconSizePx) cellContentHeight = getCellContentHeight() // Step 3. Decrease label size if (cellContentHeight > cellHeightPx) { iconTextSizePx = max( iconSizeSteps.minimumIconLabelSize, iconTextSizePx - IconSizeSteps.TEXT_STEP ) cellContentHeight = getCellContentHeight() } } return cellContentHeight } /** Calculate new cellContentHeight */ fun getCellContentHeight(): Int { val iconTextHeight = Utilities.calculateTextHeight(iconTextSizePx.toFloat()) return iconSizePx + iconDrawablePaddingPx + iconTextHeight } } src/com/android/launcher3/util/IconSizeSteps.kt +6 −0 Original line number Diff line number Diff line Loading @@ -23,12 +23,14 @@ import kotlin.math.max class IconSizeSteps(res: Resources) { private val steps: List<Int> val minimumIconLabelSize: Int init { steps = res.obtainTypedArray(R.array.icon_size_steps).use { (0 until it.length()).map { step -> it.getDimensionOrThrow(step).toInt() }.sorted() } minimumIconLabelSize = res.getDimensionPixelSize(R.dimen.minimum_icon_label_size) } fun minimumIconSize(): Int = steps[0] Loading @@ -44,4 +46,8 @@ class IconSizeSteps(res: Resources) { private fun getIndexForIconSize(iconSizePx: Int): Int { return max(0, steps.indexOfFirst { iconSizePx <= it }) } companion object { internal const val TEXT_STEP = 1 } } tests/src/com/android/launcher3/util/CellContentDimensionsTest.kt 0 → 100644 +148 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.util import android.content.Context import android.content.res.Configuration import android.util.DisplayMetrics import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class CellContentDimensionsTest { private var context: Context? = null private val runningContext: Context = ApplicationProvider.getApplicationContext() private lateinit var iconSizeSteps: IconSizeSteps @Before fun setup() { // 160dp makes 1px = 1dp val config = Configuration(runningContext.resources.configuration).apply { this.densityDpi = DisplayMetrics.DENSITY_DEFAULT } context = runningContext.createConfigurationContext(config) iconSizeSteps = IconSizeSteps(context!!.resources) } @Test fun dimensionsFitTheCell() { val cellSize = Pair(80, 104) val cellContentDimensions = CellContentDimensions(iconSizePx = 66, iconDrawablePaddingPx = 8, iconTextSizePx = 14) val contentHeight = cellContentDimensions.resizeToFitCellHeight(cellSize.second, iconSizeSteps) assertThat(contentHeight).isEqualTo(93) cellContentDimensions.run { assertThat(iconSizePx).isEqualTo(66) assertThat(iconDrawablePaddingPx).isEqualTo(8) assertThat(iconTextSizePx).isEqualTo(14) } } @Test fun decreasePadding() { val cellSize = Pair(67, 87) val cellContentDimensions = CellContentDimensions(iconSizePx = 66, iconDrawablePaddingPx = 8, iconTextSizePx = 14) val contentHeight = cellContentDimensions.resizeToFitCellHeight(cellSize.second, iconSizeSteps) assertThat(contentHeight).isEqualTo(87) cellContentDimensions.run { assertThat(iconSizePx).isEqualTo(66) assertThat(iconDrawablePaddingPx).isEqualTo(2) assertThat(iconTextSizePx).isEqualTo(14) } } @Test fun decreaseIcon() { val cellSize = Pair(65, 84) val cellContentDimensions = CellContentDimensions(iconSizePx = 66, iconDrawablePaddingPx = 8, iconTextSizePx = 14) val contentHeight = cellContentDimensions.resizeToFitCellHeight(cellSize.second, iconSizeSteps) assertThat(contentHeight).isEqualTo(82) cellContentDimensions.run { assertThat(iconSizePx).isEqualTo(63) assertThat(iconDrawablePaddingPx).isEqualTo(0) assertThat(iconTextSizePx).isEqualTo(14) } } @Test fun decreaseText() { val cellSize = Pair(63, 81) val cellContentDimensions = CellContentDimensions(iconSizePx = 66, iconDrawablePaddingPx = 8, iconTextSizePx = 14) val contentHeight = cellContentDimensions.resizeToFitCellHeight(cellSize.second, iconSizeSteps) assertThat(contentHeight).isEqualTo(81) cellContentDimensions.run { assertThat(iconSizePx).isEqualTo(63) assertThat(iconDrawablePaddingPx).isEqualTo(0) assertThat(iconTextSizePx).isEqualTo(13) } } @Test fun decreaseIconAndTextTwoSteps() { val cellSize = Pair(60, 78) val cellContentDimensions = CellContentDimensions(iconSizePx = 66, iconDrawablePaddingPx = 8, iconTextSizePx = 14) val contentHeight = cellContentDimensions.resizeToFitCellHeight(cellSize.second, iconSizeSteps) assertThat(contentHeight).isEqualTo(77) cellContentDimensions.run { assertThat(iconSizePx).isEqualTo(61) assertThat(iconDrawablePaddingPx).isEqualTo(0) assertThat(iconTextSizePx).isEqualTo(12) } } @Test fun decreaseIconAndTextToMinimum() { val cellSize = Pair(52, 63) val cellContentDimensions = CellContentDimensions(iconSizePx = 66, iconDrawablePaddingPx = 8, iconTextSizePx = 14) val contentHeight = cellContentDimensions.resizeToFitCellHeight(cellSize.second, iconSizeSteps) assertThat(contentHeight).isEqualTo(63) cellContentDimensions.run { assertThat(iconSizePx).isEqualTo(52) assertThat(iconDrawablePaddingPx).isEqualTo(0) assertThat(iconTextSizePx).isEqualTo(8) } } } Loading
res/values/config.xml +2 −0 Original line number Diff line number Diff line Loading @@ -242,6 +242,8 @@ <item>@dimen/iconSize72dp</item> </integer-array> <dimen name="minimum_icon_label_size">8sp</dimen> <!-- Used for custom widgets --> <array name="custom_widget_providers"/> </resources>
src/com/android/launcher3/DeviceProfile.java +19 −20 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ import com.android.launcher3.responsive.FolderSpecs; import com.android.launcher3.responsive.HotseatSpecs; import com.android.launcher3.responsive.WorkspaceSpecs; import com.android.launcher3.uioverrides.ApiWrapper; import com.android.launcher3.util.CellContentDimensions; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.Info; import com.android.launcher3.util.IconSizeSteps; Loading Loading @@ -924,14 +925,11 @@ public class DeviceProfile { - iconTextHeight; if (mIsResponsiveGrid) { // Hide text only if doesn't fit inside the cell for responsive grid if (workspaceCellPaddingY < 0) { iconTextSizePx = 0; iconDrawablePaddingPx = 0; int iconSizeWithOverlap = getIconSizeWithOverlap(iconSizePx); cellYPaddingPx = Math.max(0, getCellSize().y - iconSizeWithOverlap) / 2; autoResizeAllAppsCells(); } return; } Loading Loading @@ -1047,22 +1045,23 @@ public class DeviceProfile { iconSizePx = mIconSizeSteps.getIconSmallerThan(cellWidthPx); } // TODO(b/296400197): isVerticalBar shouldn't show labels anymore iconDrawablePaddingPx = getNormalizedIconDrawablePadding(); int iconTextHeight = Utilities.calculateTextHeight(iconTextSizePx); int cellContentHeight = iconSizePx + iconDrawablePaddingPx + iconTextHeight; while (iconSizePx > mIconSizeSteps.minimumIconSize() && cellContentHeight > cellHeightPx) { iconDrawablePaddingPx -= cellContentHeight - cellHeightPx; if (iconDrawablePaddingPx < 0) { // get a smaller icon size iconSizePx = mIconSizeSteps.getNextLowerIconSize(iconSizePx); iconDrawablePaddingPx = getNormalizedIconDrawablePadding(); CellContentDimensions cellContentDimensions = new CellContentDimensions(iconSizePx, iconDrawablePaddingPx, iconTextSizePx); if (isVerticalLayout) { if (cellHeightPx < iconSizePx) { cellContentDimensions.setIconSizePx( mIconSizeSteps.getIconSmallerThan(cellHeightPx)); } // calculate new cellContentHeight cellContentHeight = iconSizePx + iconDrawablePaddingPx + iconTextHeight; } else { cellContentDimensions.resizeToFitCellHeight(cellHeightPx, mIconSizeSteps); } iconSizePx = cellContentDimensions.getIconSizePx(); iconDrawablePaddingPx = cellContentDimensions.getIconDrawablePaddingPx(); iconTextSizePx = cellContentDimensions.getIconTextSizePx(); int cellContentHeight = cellContentDimensions.getCellContentHeight(); cellYPaddingPx = Math.max(0, cellHeightPx - cellContentHeight) / 2; } else if (mIsScalableGrid) { Loading
src/com/android/launcher3/util/CellContentDimensions.kt 0 → 100644 +69 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.util import com.android.launcher3.Utilities import kotlin.math.max class CellContentDimensions( var iconSizePx: Int, var iconDrawablePaddingPx: Int, var iconTextSizePx: Int ) { /** * This method goes through some steps to reduce the padding between icon and label, icon size * and then label size, until it can fit in the [cellHeightPx]. * * @return the height of the content after being sized down. */ fun resizeToFitCellHeight(cellHeightPx: Int, iconSizeSteps: IconSizeSteps): Int { var cellContentHeight = getCellContentHeight() // Step 1. Decrease drawable padding if (cellContentHeight > cellHeightPx) { val diff = cellContentHeight - cellHeightPx iconDrawablePaddingPx = max(0, iconDrawablePaddingPx - diff) cellContentHeight = getCellContentHeight() } while ( (iconTextSizePx > iconSizeSteps.minimumIconLabelSize || iconSizePx > iconSizeSteps.minimumIconSize()) && cellContentHeight > cellHeightPx ) { // Step 2. Decrease icon size iconSizePx = iconSizeSteps.getNextLowerIconSize(iconSizePx) cellContentHeight = getCellContentHeight() // Step 3. Decrease label size if (cellContentHeight > cellHeightPx) { iconTextSizePx = max( iconSizeSteps.minimumIconLabelSize, iconTextSizePx - IconSizeSteps.TEXT_STEP ) cellContentHeight = getCellContentHeight() } } return cellContentHeight } /** Calculate new cellContentHeight */ fun getCellContentHeight(): Int { val iconTextHeight = Utilities.calculateTextHeight(iconTextSizePx.toFloat()) return iconSizePx + iconDrawablePaddingPx + iconTextHeight } }
src/com/android/launcher3/util/IconSizeSteps.kt +6 −0 Original line number Diff line number Diff line Loading @@ -23,12 +23,14 @@ import kotlin.math.max class IconSizeSteps(res: Resources) { private val steps: List<Int> val minimumIconLabelSize: Int init { steps = res.obtainTypedArray(R.array.icon_size_steps).use { (0 until it.length()).map { step -> it.getDimensionOrThrow(step).toInt() }.sorted() } minimumIconLabelSize = res.getDimensionPixelSize(R.dimen.minimum_icon_label_size) } fun minimumIconSize(): Int = steps[0] Loading @@ -44,4 +46,8 @@ class IconSizeSteps(res: Resources) { private fun getIndexForIconSize(iconSizePx: Int): Int { return max(0, steps.indexOfFirst { iconSizePx <= it }) } companion object { internal const val TEXT_STEP = 1 } }
tests/src/com/android/launcher3/util/CellContentDimensionsTest.kt 0 → 100644 +148 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.util import android.content.Context import android.content.res.Configuration import android.util.DisplayMetrics import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @SmallTest @RunWith(AndroidJUnit4::class) class CellContentDimensionsTest { private var context: Context? = null private val runningContext: Context = ApplicationProvider.getApplicationContext() private lateinit var iconSizeSteps: IconSizeSteps @Before fun setup() { // 160dp makes 1px = 1dp val config = Configuration(runningContext.resources.configuration).apply { this.densityDpi = DisplayMetrics.DENSITY_DEFAULT } context = runningContext.createConfigurationContext(config) iconSizeSteps = IconSizeSteps(context!!.resources) } @Test fun dimensionsFitTheCell() { val cellSize = Pair(80, 104) val cellContentDimensions = CellContentDimensions(iconSizePx = 66, iconDrawablePaddingPx = 8, iconTextSizePx = 14) val contentHeight = cellContentDimensions.resizeToFitCellHeight(cellSize.second, iconSizeSteps) assertThat(contentHeight).isEqualTo(93) cellContentDimensions.run { assertThat(iconSizePx).isEqualTo(66) assertThat(iconDrawablePaddingPx).isEqualTo(8) assertThat(iconTextSizePx).isEqualTo(14) } } @Test fun decreasePadding() { val cellSize = Pair(67, 87) val cellContentDimensions = CellContentDimensions(iconSizePx = 66, iconDrawablePaddingPx = 8, iconTextSizePx = 14) val contentHeight = cellContentDimensions.resizeToFitCellHeight(cellSize.second, iconSizeSteps) assertThat(contentHeight).isEqualTo(87) cellContentDimensions.run { assertThat(iconSizePx).isEqualTo(66) assertThat(iconDrawablePaddingPx).isEqualTo(2) assertThat(iconTextSizePx).isEqualTo(14) } } @Test fun decreaseIcon() { val cellSize = Pair(65, 84) val cellContentDimensions = CellContentDimensions(iconSizePx = 66, iconDrawablePaddingPx = 8, iconTextSizePx = 14) val contentHeight = cellContentDimensions.resizeToFitCellHeight(cellSize.second, iconSizeSteps) assertThat(contentHeight).isEqualTo(82) cellContentDimensions.run { assertThat(iconSizePx).isEqualTo(63) assertThat(iconDrawablePaddingPx).isEqualTo(0) assertThat(iconTextSizePx).isEqualTo(14) } } @Test fun decreaseText() { val cellSize = Pair(63, 81) val cellContentDimensions = CellContentDimensions(iconSizePx = 66, iconDrawablePaddingPx = 8, iconTextSizePx = 14) val contentHeight = cellContentDimensions.resizeToFitCellHeight(cellSize.second, iconSizeSteps) assertThat(contentHeight).isEqualTo(81) cellContentDimensions.run { assertThat(iconSizePx).isEqualTo(63) assertThat(iconDrawablePaddingPx).isEqualTo(0) assertThat(iconTextSizePx).isEqualTo(13) } } @Test fun decreaseIconAndTextTwoSteps() { val cellSize = Pair(60, 78) val cellContentDimensions = CellContentDimensions(iconSizePx = 66, iconDrawablePaddingPx = 8, iconTextSizePx = 14) val contentHeight = cellContentDimensions.resizeToFitCellHeight(cellSize.second, iconSizeSteps) assertThat(contentHeight).isEqualTo(77) cellContentDimensions.run { assertThat(iconSizePx).isEqualTo(61) assertThat(iconDrawablePaddingPx).isEqualTo(0) assertThat(iconTextSizePx).isEqualTo(12) } } @Test fun decreaseIconAndTextToMinimum() { val cellSize = Pair(52, 63) val cellContentDimensions = CellContentDimensions(iconSizePx = 66, iconDrawablePaddingPx = 8, iconTextSizePx = 14) val contentHeight = cellContentDimensions.resizeToFitCellHeight(cellSize.second, iconSizeSteps) assertThat(contentHeight).isEqualTo(63) cellContentDimensions.run { assertThat(iconSizePx).isEqualTo(52) assertThat(iconDrawablePaddingPx).isEqualTo(0) assertThat(iconTextSizePx).isEqualTo(8) } } }