diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 7be584e932..de17eb7b4f 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -115,8 +115,6 @@ - - @@ -132,12 +130,6 @@ - - - - - - diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 736142f190..a35f598686 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -25,6 +25,8 @@ import android.graphics.Rect; import android.util.DisplayMetrics; import android.view.Surface; +import androidx.annotation.Nullable; + import com.android.launcher3.CellLayout.ContainerType; import com.android.launcher3.graphics.IconShape; import com.android.launcher3.icons.DotRenderer; @@ -34,6 +36,8 @@ import com.android.launcher3.util.DefaultDisplay; public class DeviceProfile { public final InvariantDeviceProfile inv; + // IDP with no grid override values. + @Nullable private final InvariantDeviceProfile originalIdp; // Device properties public final boolean isTablet; @@ -134,10 +138,11 @@ public class DeviceProfile { public DotRenderer mDotRendererAllApps; public DeviceProfile(Context context, InvariantDeviceProfile inv, - Point minSize, Point maxSize, + InvariantDeviceProfile originalIDP, Point minSize, Point maxSize, int width, int height, boolean isLandscape, boolean isMultiWindowMode) { this.inv = inv; + this.originalIdp = inv; this.isLandscape = isLandscape; this.isMultiWindowMode = isMultiWindowMode; @@ -229,6 +234,19 @@ public class DeviceProfile { // Recalculate the available dimensions using the new hotseat size. updateAvailableDimensions(dm, res); } + + if (originalIDP != null) { + // Grid size change should not affect All Apps UI, so we use the original profile + // measurements here. + DeviceProfile originalProfile = isLandscape + ? originalIDP.landscapeProfile + : originalIDP.portraitProfile; + allAppsIconSizePx = originalProfile.iconSizePx; + allAppsIconTextSizePx = originalProfile.iconTextSizePx; + allAppsCellHeightPx = originalProfile.allAppsCellHeightPx; + allAppsIconDrawablePaddingPx = originalProfile.iconDrawablePaddingOriginalPx; + allAppsCellWidthPx = allAppsIconSizePx + allAppsIconDrawablePaddingPx; + } updateWorkspacePadding(); // This is done last, after iconSizePx is calculated above. @@ -241,8 +259,8 @@ public class DeviceProfile { public DeviceProfile copy(Context context) { Point size = new Point(availableWidthPx, availableHeightPx); - return new DeviceProfile(context, inv, size, size, widthPx, heightPx, isLandscape, - isMultiWindowMode); + return new DeviceProfile(context, inv, originalIdp, size, size, widthPx, heightPx, + isLandscape, isMultiWindowMode); } public DeviceProfile getMultiWindowProfile(Context context, Point mwSize) { @@ -253,8 +271,8 @@ public class DeviceProfile { // In multi-window mode, we can have widthPx = availableWidthPx // and heightPx = availableHeightPx because Launcher uses the InvariantDeviceProfiles' // widthPx and heightPx values where it's needed. - DeviceProfile profile = new DeviceProfile(context, inv, mwSize, mwSize, mwSize.x, mwSize.y, - isLandscape, true); + DeviceProfile profile = new DeviceProfile(context, inv, originalIdp, mwSize, mwSize, + mwSize.x, mwSize.y, isLandscape, true); // If there isn't enough vertical cell padding with the labels displayed, hide the labels. float workspaceCellPaddingY = profile.getCellSize().y - profile.iconSizePx @@ -338,18 +356,10 @@ public class DeviceProfile { } cellWidthPx = iconSizePx + iconDrawablePaddingPx; - // All apps - if (allAppsHasDifferentNumColumns()) { - allAppsIconSizePx = ResourceUtils.pxFromDp(inv.allAppsIconSize, dm); - allAppsIconTextSizePx = Utilities.pxFromSp(inv.allAppsIconTextSize, dm); - allAppsCellHeightPx = getCellSize(inv.numAllAppsColumns, inv.numAllAppsColumns).y; - allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx; - } else { - allAppsIconSizePx = iconSizePx; - allAppsIconTextSizePx = iconTextSizePx; - allAppsIconDrawablePaddingPx = iconDrawablePaddingPx; - allAppsCellHeightPx = getCellSize().y; - } + allAppsIconSizePx = iconSizePx; + allAppsIconTextSizePx = iconTextSizePx; + allAppsIconDrawablePaddingPx = iconDrawablePaddingPx; + allAppsCellHeightPx = getCellSize().y; allAppsCellWidthPx = allAppsIconSizePx + allAppsIconDrawablePaddingPx; if (isVerticalBarLayout()) { diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 310a9e92ff..d66ba73175 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -58,6 +58,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; public class InvariantDeviceProfile { @@ -191,54 +192,11 @@ public class InvariantDeviceProfile { Point smallestSize = new Point(displayInfo.smallestSize); Point largestSize = new Point(displayInfo.largestSize); - ArrayList allOptions = getPredefinedDeviceProfiles(context, gridName); // This guarantees that width < height float minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y), displayInfo.metrics); float minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y), displayInfo.metrics); - // Sort the profiles based on the closeness to the device size - Collections.sort(allOptions, (a, b) -> - Float.compare(dist(minWidthDps, minHeightDps, a.minWidthDps, a.minHeightDps), - dist(minWidthDps, minHeightDps, b.minWidthDps, b.minHeightDps))); - DisplayOption interpolatedDisplayOption = - invDistWeightedInterpolate(minWidthDps, minHeightDps, allOptions); - - GridOption closestProfile = allOptions.get(0).grid; - numRows = closestProfile.numRows; - numColumns = closestProfile.numColumns; - numHotseatIcons = closestProfile.numHotseatIcons; - defaultLayoutId = closestProfile.defaultLayoutId; - demoModeLayoutId = closestProfile.demoModeLayoutId; - numFolderRows = closestProfile.numFolderRows; - numFolderColumns = closestProfile.numFolderColumns; - numAllAppsColumns = closestProfile.numAllAppsColumns; - - mExtraAttrs = closestProfile.extraAttrs; - - if (!closestProfile.name.equals(gridName)) { - Utilities.getPrefs(context).edit() - .putString(KEY_IDP_GRID_NAME, closestProfile.name).apply(); - } - - iconSize = interpolatedDisplayOption.iconSize; - iconShapePath = getIconShapePath(context); - landscapeIconSize = interpolatedDisplayOption.landscapeIconSize; - iconBitmapSize = ResourceUtils.pxFromDp(iconSize, displayInfo.metrics); - iconTextSize = interpolatedDisplayOption.iconTextSize; - fillResIconDpi = getLauncherIconDensity(iconBitmapSize); - - if (Utilities.getPrefs(context).getBoolean(GRID_OPTIONS_PREFERENCE_KEY, false)) { - allAppsIconSize = interpolatedDisplayOption.allAppsIconSize; - allAppsIconTextSize = interpolatedDisplayOption.allAppsIconTextSize; - } else { - allAppsIconSize = iconSize; - allAppsIconTextSize = iconTextSize; - } - - // If the partner customization apk contains any grid overrides, apply them - // Supported overrides: numRows, numColumns, iconSize - applyPartnerDeviceProfileOverrides(context, displayInfo.metrics); Point realSize = new Point(displayInfo.realSize); // The real size never changes. smallSide and largeSide will remain the @@ -246,10 +204,64 @@ public class InvariantDeviceProfile { int smallSide = Math.min(realSize.x, realSize.y); int largeSide = Math.max(realSize.x, realSize.y); - landscapeProfile = new DeviceProfile(context, this, smallestSize, largestSize, - largeSide, smallSide, true /* isLandscape */, false /* isMultiWindowMode */); - portraitProfile = new DeviceProfile(context, this, smallestSize, largestSize, - smallSide, largeSide, false /* isLandscape */, false /* isMultiWindowMode */); + // We want a list of all options as well as the list of filtered options. This allows us + // to have a consistent UI for areas that the grid size change should not affect + // ie. All Apps should be consistent between grid sizes. + ArrayList allOptions = new ArrayList<>(); + ArrayList filteredOptions = new ArrayList<>(); + getPredefinedDeviceProfiles(context, gridName, filteredOptions, allOptions); + + if (allOptions.isEmpty() && filteredOptions.isEmpty()) { + throw new RuntimeException("No display option with canBeDefault=true"); + } + + // Sort the profiles based on the closeness to the device size + Comparator comparator = (a, b) -> Float.compare(dist(minWidthDps, + minHeightDps, a.minWidthDps, a.minHeightDps), + dist(minWidthDps, minHeightDps, b.minWidthDps, b.minHeightDps)); + + // Calculate the device profiles as if there is no grid override. + Collections.sort(allOptions, comparator); + DisplayOption interpolatedDisplayOption = + invDistWeightedInterpolate(minWidthDps, minHeightDps, allOptions); + initGridOption(context, allOptions, interpolatedDisplayOption, displayInfo.metrics); + + // Create IDP with no grid override values. + InvariantDeviceProfile originalIDP = new InvariantDeviceProfile(this); + originalIDP.landscapeProfile = new DeviceProfile(context, this, null, smallestSize, + largestSize, largeSide, smallSide, true /* isLandscape */, + false /* isMultiWindowMode */); + originalIDP.portraitProfile = new DeviceProfile(context, this, null, smallestSize, + largestSize, smallSide, largeSide, false /* isLandscape */, + false /* isMultiWindowMode */); + + if (filteredOptions.isEmpty()) { + filteredOptions = allOptions; + + landscapeProfile = originalIDP.landscapeProfile; + portraitProfile = originalIDP.portraitProfile; + } else { + Collections.sort(filteredOptions, comparator); + interpolatedDisplayOption = + invDistWeightedInterpolate(minWidthDps, minHeightDps, filteredOptions); + + initGridOption(context, filteredOptions, interpolatedDisplayOption, + displayInfo.metrics); + numAllAppsColumns = originalIDP.numAllAppsColumns; + + landscapeProfile = new DeviceProfile(context, this, originalIDP, smallestSize, + largestSize, largeSide, smallSide, true /* isLandscape */, + false /* isMultiWindowMode */); + portraitProfile = new DeviceProfile(context, this, originalIDP, smallestSize, + largestSize, smallSide, largeSide, false /* isLandscape */, + false /* isMultiWindowMode */); + } + + GridOption closestProfile = filteredOptions.get(0).grid; + if (!closestProfile.name.equals(gridName)) { + Utilities.getPrefs(context).edit() + .putString(KEY_IDP_GRID_NAME, closestProfile.name).apply(); + } // We need to ensure that there is enough extra space in the wallpaper // for the intended parallax effects @@ -267,6 +279,33 @@ public class InvariantDeviceProfile { return closestProfile.name; } + private void initGridOption(Context context, ArrayList options, + DisplayOption displayOption, DisplayMetrics metrics) { + GridOption closestProfile = options.get(0).grid; + numRows = closestProfile.numRows; + numColumns = closestProfile.numColumns; + numHotseatIcons = closestProfile.numHotseatIcons; + defaultLayoutId = closestProfile.defaultLayoutId; + demoModeLayoutId = closestProfile.demoModeLayoutId; + numFolderRows = closestProfile.numFolderRows; + numFolderColumns = closestProfile.numFolderColumns; + numAllAppsColumns = numColumns; + + mExtraAttrs = closestProfile.extraAttrs; + + iconSize = displayOption.iconSize; + iconShapePath = getIconShapePath(context); + landscapeIconSize = displayOption.landscapeIconSize; + iconBitmapSize = ResourceUtils.pxFromDp(iconSize, metrics); + iconTextSize = displayOption.iconTextSize; + fillResIconDpi = getLauncherIconDensity(iconBitmapSize); + + // If the partner customization apk contains any grid overrides, apply them + // Supported overrides: numRows, numColumns, iconSize + applyPartnerDeviceProfileOverrides(context, metrics); + } + + @Nullable public TypedValue getAttrValue(int attr) { return mExtraAttrs == null ? null : mExtraAttrs.get(attr); @@ -344,7 +383,13 @@ public class InvariantDeviceProfile { } } - static ArrayList getPredefinedDeviceProfiles(Context context, String gridName) { + /** + * @param gridName The current grid name. + * @param filteredOptionsOut List filled with all the filtered options based on gridName. + * @param allOptionsOut List filled with all the options that can be the default option. + */ + static void getPredefinedDeviceProfiles(Context context, String gridName, + ArrayList filteredOptionsOut, ArrayList allOptionsOut) { ArrayList profiles = new ArrayList<>(); try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) { final int depth = parser.getDepth(); @@ -371,26 +416,19 @@ public class InvariantDeviceProfile { throw new RuntimeException(e); } - ArrayList filteredProfiles = new ArrayList<>(); if (!TextUtils.isEmpty(gridName)) { for (DisplayOption option : profiles) { if (gridName.equals(option.grid.name)) { - filteredProfiles.add(option); + filteredOptionsOut.add(option); } } } - if (filteredProfiles.isEmpty()) { - // No grid found, use the default options - for (DisplayOption option : profiles) { - if (option.canBeDefault) { - filteredProfiles.add(option); - } + + for (DisplayOption option : profiles) { + if (option.canBeDefault) { + allOptionsOut.add(option); } } - if (filteredProfiles.isEmpty()) { - throw new RuntimeException("No display option with canBeDefault=true"); - } - return filteredProfiles; } private int getLauncherIconDensity(int requiredSize) { @@ -514,8 +552,6 @@ public class InvariantDeviceProfile { private final int numHotseatIcons; - private final int numAllAppsColumns; - private final int defaultLayoutId; private final int demoModeLayoutId; @@ -538,8 +574,6 @@ public class InvariantDeviceProfile { R.styleable.GridDisplayOption_numFolderRows, numRows); numFolderColumns = a.getInt( R.styleable.GridDisplayOption_numFolderColumns, numColumns); - numAllAppsColumns = a.getInt( - R.styleable.GridDisplayOption_numAllAppsColumns, numColumns); a.recycle(); @@ -559,8 +593,6 @@ public class InvariantDeviceProfile { private float iconSize; private float iconTextSize; private float landscapeIconSize; - private float allAppsIconSize; - private float allAppsIconTextSize; DisplayOption(GridOption grid, Context context, AttributeSet attrs) { this.grid = grid; @@ -579,10 +611,6 @@ public class InvariantDeviceProfile { iconSize); iconTextSize = a.getFloat(R.styleable.ProfileDisplayOption_iconTextSize, 0); - allAppsIconSize = a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconSize, - iconSize); - allAppsIconTextSize = a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconTextSize, - iconTextSize); a.recycle(); } @@ -597,18 +625,14 @@ public class InvariantDeviceProfile { private DisplayOption multiply(float w) { iconSize *= w; landscapeIconSize *= w; - allAppsIconSize *= w; iconTextSize *= w; - allAppsIconTextSize *= w; return this; } private DisplayOption add(DisplayOption p) { iconSize += p.iconSize; landscapeIconSize += p.landscapeIconSize; - allAppsIconSize += p.allAppsIconSize; iconTextSize += p.iconTextSize; - allAppsIconTextSize += p.allAppsIconTextSize; return this; } }