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:
commit
643598987b
|
@ -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">
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue