Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03951ba5 authored by Jordan Silva's avatar Jordan Silva Committed by Android (Google) Code Review
Browse files

Merge "Decrease icon size by steps" into udc-qpr-dev

parents ca533b12 2759aa34
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -217,4 +217,28 @@
    <!-- Whether the floating rotation button should be on the left/right in the device's natural
         orientation -->
    <bool name="floating_rotation_button_position_left">true</bool>

    <!--  Mapping of visual icon size to XML value http://b/235886078  -->
    <dimen name="iconSize48dp">52dp</dimen>
    <dimen name="iconSize50dp">55dp</dimen>
    <dimen name="iconSize52dp">57dp</dimen>
    <dimen name="iconSize54dp">59dp</dimen>
    <dimen name="iconSize56dp">61dp</dimen>
    <dimen name="iconSize58dp">63dp</dimen>
    <dimen name="iconSize60dp">66dp</dimen>
    <dimen name="iconSize66dp">72dp</dimen>
    <dimen name="iconSize72dp">79dp</dimen>

    <!--  Icon size steps in dp  -->
    <integer-array name="icon_size_steps">
        <item>@dimen/iconSize48dp</item>
        <item>@dimen/iconSize50dp</item>
        <item>@dimen/iconSize52dp</item>
        <item>@dimen/iconSize54dp</item>
        <item>@dimen/iconSize56dp</item>
        <item>@dimen/iconSize58dp</item>
        <item>@dimen/iconSize60dp</item>
        <item>@dimen/iconSize66dp</item>
        <item>@dimen/iconSize72dp</item>
    </integer-array>
</resources>
+37 −6
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import com.android.launcher3.responsive.CalculatedAllAppsSpec;
import com.android.launcher3.uioverrides.ApiWrapper;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.DisplayController.Info;
import com.android.launcher3.util.IconSizeSteps;
import com.android.launcher3.util.ResourceHelper;
import com.android.launcher3.util.WindowBounds;
import com.android.launcher3.workspace.CalculatedWorkspaceSpec;
@@ -83,6 +84,7 @@ public class DeviceProfile {
    public final InvariantDeviceProfile inv;
    private final Info mInfo;
    private final DisplayMetrics mMetrics;
    private final IconSizeSteps mIconSizeSteps;

    // Device properties
    public final boolean isTablet;
@@ -330,6 +332,8 @@ public class DeviceProfile {
        final Resources res = context.getResources();
        mMetrics = res.getDisplayMetrics();

        mIconSizeSteps = mIsResponsiveGrid ? new IconSizeSteps(res) : null;

        // Determine sizes.
        widthPx = windowBounds.bounds.width();
        heightPx = windowBounds.bounds.height();
@@ -535,12 +539,16 @@ public class DeviceProfile {
        // for the available height to be correct
        if (mIsResponsiveGrid) {
            mWorkspaceSpecs = new WorkspaceSpecs(new ResourceHelper(context, inv.workspaceSpecsId));
            int availableResponsiveWidth =
                    availableWidthPx - (isVerticalBarLayout() ? hotseatBarSizePx : 0);
            // don't use availableHeightPx because it subtracts bottom padding,
            // but the workspace go behind it
            int availableResponsiveHeight =
                    heightPx - mInsets.top - (isVerticalBarLayout() ? 0 : hotseatBarSizePx);
            mResponsiveWidthSpec = mWorkspaceSpecs.getCalculatedWidthSpec(inv.numColumns,
                    availableWidthPx);
                    availableResponsiveWidth);
            mResponsiveHeightSpec = mWorkspaceSpecs.getCalculatedHeightSpec(inv.numRows,
                    // don't use availableHeightPx because it subtracts bottom padding,
                    // but the hotseat go behind it
                    heightPx - mInsets.top - hotseatBarSizePx);
                    availableResponsiveHeight);

            mAllAppsSpecs = new AllAppsSpecs(new ResourceHelper(context, inv.allAppsSpecsId));
            mAllAppsResponsiveWidthSpec = mAllAppsSpecs.getCalculatedWidthSpec(inv.numColumns,
@@ -926,9 +934,32 @@ public class DeviceProfile {

            cellWidthPx = mResponsiveWidthSpec.getCellSizePx();
            cellHeightPx = mResponsiveHeightSpec.getCellSizePx();
            cellYPaddingPx = Math.max(0, cellHeightPx - cellContentHeight) / 2;

            // TODO(b/283929701): decrease icon size if content doesn't fit on cell
            if (cellWidthPx < iconSizePx) {
                // get a smaller icon size
                iconSizePx = mIconSizeSteps.getIconSmallerThan(cellWidthPx);
                // calculate new cellContentHeight
                cellContentHeight = iconSizePx + cellTextAndPaddingHeight;
            }

            while (iconSizePx > mIconSizeSteps.minimumIconSize()
                    && cellContentHeight > cellHeightPx) {
                int extraHeightRequired = cellContentHeight - cellHeightPx;
                int newPadding = iconDrawablePaddingPx - extraHeightRequired;
                if (newPadding >= 0) {
                    // Responsive uses the padding without scaling
                    iconDrawablePaddingPx = iconDrawablePaddingOriginalPx = newPadding;
                    cellTextAndPaddingHeight =
                            iconDrawablePaddingPx + Utilities.calculateTextHeight(iconTextSizePx);
                } else {
                    // get a smaller icon size
                    iconSizePx = mIconSizeSteps.getNextLowerIconSize(iconSizePx);
                }
                // calculate new cellContentHeight
                cellContentHeight = iconSizePx + cellTextAndPaddingHeight;
            }

            cellYPaddingPx = Math.max(0, cellHeightPx - cellContentHeight) / 2;
        } else if (mIsScalableGrid) {
            cellWidthPx = pxFromDp(inv.minCellSize[mTypeIndex].x, mMetrics, scale);
            cellHeightPx = pxFromDp(inv.minCellSize[mTypeIndex].y, mMetrics, scale);
+47 −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.res.Resources
import androidx.core.content.res.getDimensionOrThrow
import androidx.core.content.res.use
import com.android.launcher3.R
import kotlin.math.max

class IconSizeSteps(res: Resources) {
    private val steps: List<Int>

    init {
        steps =
            res.obtainTypedArray(R.array.icon_size_steps).use {
                (0 until it.length()).map { step -> it.getDimensionOrThrow(step).toInt() }.sorted()
            }
    }

    fun minimumIconSize(): Int = steps[0]

    fun getNextLowerIconSize(iconSizePx: Int): Int {
        return steps[max(0, getIndexForIconSize(iconSizePx) - 1)]
    }

    fun getIconSmallerThan(cellWidth: Int): Int {
        return steps.lastOrNull { it <= cellWidth } ?: steps[0]
    }

    private fun getIndexForIconSize(iconSizePx: Int): Int {
        return max(0, steps.indexOfFirst { iconSizePx <= it })
    }
}
+67 −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 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.Assert.*
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@RunWith(AndroidJUnit4::class)
class IconSizeStepsTest {
    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 = 160 }
        context = runningContext.createConfigurationContext(config)
        iconSizeSteps = IconSizeSteps(context!!.resources)
    }

    @Test
    fun minimumIconSize() {
        assertThat(iconSizeSteps.minimumIconSize()).isEqualTo(52)
    }

    @Test
    fun getNextLowerIconSize() {
        assertThat(iconSizeSteps.getNextLowerIconSize(66)).isEqualTo(63)

        // Assert that never goes below minimum
        assertThat(iconSizeSteps.getNextLowerIconSize(52)).isEqualTo(52)
        assertThat(iconSizeSteps.getNextLowerIconSize(30)).isEqualTo(52)
    }

    @Test
    fun getIconSmallerThan() {
        assertThat(iconSizeSteps.getIconSmallerThan(60)).isEqualTo(59)

        // Assert that never goes below minimum
        assertThat(iconSizeSteps.getIconSmallerThan(52)).isEqualTo(52)
        assertThat(iconSizeSteps.getIconSmallerThan(30)).isEqualTo(52)
    }
}