Merge "Have consistent All Apps UI between grid size changes." into ub-launcher3-qt-future-dev

am: c3a688a973

Change-Id: I6c9d825e85f55bd3160ab5e2a37e707f3f525459
This commit is contained in:
Jonathan Miranda 2019-10-16 15:51:36 -07:00 committed by android-build-merger
commit 643598987b
3 changed files with 125 additions and 99 deletions

View File

@ -115,8 +115,6 @@
<attr name="numFolderColumns" format="integer" />
<!-- numHotseatIcons defaults to numColumns, if not specified -->
<attr name="numHotseatIcons" format="integer" />
<!-- numAllAppsColumns defaults to numColumns, if not specified -->
<attr name="numAllAppsColumns" format="integer" />
<attr name="defaultLayoutId" format="reference" />
<attr name="demoModeLayoutId" format="reference" />
</declare-styleable>
@ -132,12 +130,6 @@
<attr name="iconTextSize" format="float" />
<!-- If true, this display option is used to determine the default grid -->
<attr name="canBeDefault" format="boolean" />
<!-- The following values are only enabled if grid is supported. -->
<!-- allAppsIconSize defaults to iconSize, if not specified -->
<attr name="allAppsIconSize" format="float" />
<!-- allAppsIconTextSize defaults to iconTextSize, if not specified -->
<attr name="allAppsIconTextSize" format="float" />
</declare-styleable>
<declare-styleable name="CellLayout">

View File

@ -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()) {

View File

@ -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<DisplayOption> 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<DisplayOption> allOptions = new ArrayList<>();
ArrayList<DisplayOption> 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<DisplayOption> 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<DisplayOption> 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<DisplayOption> 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<DisplayOption> filteredOptionsOut, ArrayList<DisplayOption> allOptionsOut) {
ArrayList<DisplayOption> 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<DisplayOption> 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;
}
}