Calculate hotseat width based on available width
Navigation buttons take space on the hotseat, so hotseat width (qsb width and border space between icons) should be calculated instead of having a coded value.
Bug: 223724516
Bug: 228998463
Test: manual, changing display size
Test: manual, changing hotseatBarEndOffset value
Test: HotseatWidthCalculationTest
Change-Id: Ibd4f5ff2e06afda8e7420fb744db049d2e418e14
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 0d41230..f27eb79 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -158,7 +158,7 @@
public int folderChildDrawablePaddingPx;
// Hotseat
- public final int numShownHotseatIcons;
+ public int numShownHotseatIcons;
public int hotseatCellHeightPx;
public final boolean areNavButtonsInline;
// In portrait: size = height, in landscape: size = width
@@ -362,15 +362,9 @@
&& hotseatQsbHeight > 0;
isQsbInline = inv.inlineQsb[mTypeIndex] && canQsbInline;
- // We shrink hotseat sizes regardless of orientation, if nav buttons are inline and QSB
- // might be inline in either orientations, to keep hotseat size consistent across rotation.
areNavButtonsInline = isTaskbarPresent && !isGestureMode;
- if (areNavButtonsInline && canQsbInline) {
- numShownHotseatIcons = inv.numShrunkenHotseatIcons;
- } else {
- numShownHotseatIcons =
- isTwoPanels ? inv.numDatabaseHotseatIcons : inv.numShownHotseatIcons;
- }
+ numShownHotseatIcons =
+ isTwoPanels ? inv.numDatabaseHotseatIcons : inv.numShownHotseatIcons;
numShownAllAppsColumns =
isTwoPanels ? inv.numDatabaseAllAppsColumns : inv.numAllAppsColumns;
@@ -460,8 +454,7 @@
updateWorkspacePadding();
// Hotseat and QSB width depends on updated cellSize and workspace padding
- hotseatBorderSpace = calculateHotseatBorderSpace();
- hotseatQsbWidth = calculateQsbWidth();
+ recalculateHotseatWidthAndBorderSpace(res);
// AllApps height calculation depends on updated cellSize
if (isTablet) {
@@ -499,7 +492,7 @@
* QSB width is always calculated because when in 3 button nav the width doesn't follow the
* width of the hotseat.
*/
- private int calculateQsbWidth() {
+ private int calculateQsbWidth(int hotseatBorderSpace) {
if (isQsbInline) {
int columns = getPanelCount() * inv.numColumns;
return getIconToIconWidthForColumns(columns)
@@ -546,6 +539,70 @@
}
}
+ private void recalculateHotseatWidthAndBorderSpace(Resources res) {
+ hotseatBorderSpace = calculateHotseatBorderSpace();
+ hotseatQsbWidth = calculateQsbWidth(hotseatBorderSpace);
+ // Spaces should be correct when there nav buttons are not inline
+ if (!areNavButtonsInline) {
+ return;
+ }
+
+ // Get the maximum width that the hotseat can be
+ int columns = getPanelCount() * inv.numColumns;
+ int maxHotseatWidth = getIconToIconWidthForColumns(columns);
+ int sideSpace = (availableWidthPx - maxHotseatWidth) / 2;
+ int inlineButtonsOverlap = Math.max(0, hotseatBarEndOffset - sideSpace);
+ // decrease how much the nav buttons go "inside" the hotseat
+ maxHotseatWidth -= inlineButtonsOverlap;
+
+ // Get how much space is required to show the hotseat with QSB
+ int requiredWidth = getHotseatRequiredWidth();
+
+ // If spaces are fine, use them
+ if (requiredWidth <= maxHotseatWidth) {
+ return;
+ }
+
+ // Calculate the difference of widths and remove a little from each space between icons
+ // and QSB if it's inline
+ int spaceDiff = requiredWidth - maxHotseatWidth;
+ int numOfSpaces = numShownHotseatIcons - (isQsbInline ? 0 : 1);
+ hotseatBorderSpace -= (spaceDiff / numOfSpaces);
+
+ int minHotseatIconSpaceDp = res.getDimensionPixelSize(R.dimen.min_hotseat_icon_space);
+ int minHotseatQsbWidthDp = res.getDimensionPixelSize(R.dimen.min_hotseat_qsb_width);
+
+ if (hotseatBorderSpace >= minHotseatIconSpaceDp) {
+ return;
+ }
+
+ // Border space can't be less than the minimum
+ hotseatBorderSpace = minHotseatIconSpaceDp;
+ requiredWidth = getHotseatRequiredWidth();
+
+ // If there is an inline qsb, change its size
+ if (isQsbInline) {
+ hotseatQsbWidth -= requiredWidth - maxHotseatWidth;
+ if (hotseatQsbWidth >= minHotseatQsbWidthDp) {
+ return;
+ }
+
+ // QSB can't be less than the minimum
+ hotseatQsbWidth = minHotseatQsbWidthDp;
+ }
+
+ // If it still doesn't fit, start removing icons
+ do {
+ numShownHotseatIcons--;
+ requiredWidth = getHotseatRequiredWidth();
+ } while (requiredWidth > maxHotseatWidth && numShownHotseatIcons > 1);
+
+ // Add back some space between the icons
+ spaceDiff = maxHotseatWidth - requiredWidth;
+ numOfSpaces = numShownHotseatIcons - (isQsbInline ? 0 : 1);
+ hotseatBorderSpace += (spaceDiff / numOfSpaces);
+ }
+
private Point getCellLayoutBorderSpace(InvariantDeviceProfile idp) {
return getCellLayoutBorderSpace(idp, 1f);
}
@@ -778,15 +835,10 @@
*/
private int calculateHotseatBorderSpace() {
if (!isScalableGrid) return 0;
- //TODO(http://b/228998082) remove this when 3 button spaces are fixed
- if (areNavButtonsInline) {
- return pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
- } else {
- int columns = inv.hotseatColumnSpan[mTypeIndex];
- float hotseatWidthPx = getIconToIconWidthForColumns(columns);
- float hotseatIconsTotalPx = iconSizePx * numShownHotseatIcons;
- return (int) (hotseatWidthPx - hotseatIconsTotalPx) / (numShownHotseatIcons - 1);
- }
+ int columns = inv.hotseatColumnSpan[mTypeIndex];
+ float hotseatWidthPx = getIconToIconWidthForColumns(columns);
+ float hotseatIconsTotalPx = iconSizePx * numShownHotseatIcons;
+ return (int) (hotseatWidthPx - hotseatIconsTotalPx) / (numShownHotseatIcons - 1);
}
@@ -1078,10 +1130,7 @@
hotseatBarSizePx - hotseatBarBottomPadding - hotseatCellHeightPx;
// Push icons to the side
- int additionalQsbSpace = isQsbInline ? hotseatQsbWidth + hotseatBorderSpace : 0;
- int requiredWidth = iconSizePx * numShownHotseatIcons
- + hotseatBorderSpace * (numShownHotseatIcons - 1)
- + additionalQsbSpace;
+ int requiredWidth = getHotseatRequiredWidth();
int hotseatWidth = Math.min(requiredWidth, availableWidthPx - hotseatBarEndOffset);
int sideSpacing = (availableWidthPx - hotseatWidth) / 2;
@@ -1090,9 +1139,9 @@
boolean isRtl = Utilities.isRtl(context.getResources());
if (isRtl) {
- hotseatBarPadding.right += additionalQsbSpace;
+ hotseatBarPadding.right += getAdditionalQsbSpace();
} else {
- hotseatBarPadding.left += additionalQsbSpace;
+ hotseatBarPadding.left += getAdditionalQsbSpace();
}
if (hotseatBarEndOffset > sideSpacing) {
@@ -1127,6 +1176,20 @@
return hotseatBarPadding;
}
+ private int getAdditionalQsbSpace() {
+ return isQsbInline ? hotseatQsbWidth + hotseatBorderSpace : 0;
+ }
+
+ /**
+ * Calculate how much space the hotseat needs to be shown completely
+ */
+ private int getHotseatRequiredWidth() {
+ int additionalQsbSpace = getAdditionalQsbSpace();
+ return iconSizePx * numShownHotseatIcons
+ + hotseatBorderSpace * (numShownHotseatIcons - 1)
+ + additionalQsbSpace;
+ }
+
/**
* Returns the number of pixels the QSB is translated from the bottom of the screen.
*/
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 67620e3..21eba00 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -128,7 +128,6 @@
public PointF[] borderSpaces;
public float folderBorderSpace;
- public float[] hotseatBorderSpaces;
public int inlineNavButtonsEndSpacing;
public float[] horizontalMargin;
@@ -146,11 +145,6 @@
public int numShownHotseatIcons;
/**
- * Number of icons inside the hotseat area when using 3 buttons navigation.
- */
- public int numShrunkenHotseatIcons;
-
- /**
* Number of icons inside the hotseat area that is stored in the database. This is greater than
* or equal to numnShownHotseatIcons, allowing for a seamless transition between two hotseat
* sizes that share the same DB.
@@ -176,7 +170,7 @@
public String dbFile;
public int defaultLayoutId;
int demoModeLayoutId;
- boolean[] inlineQsb = new boolean[COUNT_SIZES];
+ public boolean[] inlineQsb = new boolean[COUNT_SIZES];
/**
* An immutable list of supported profiles.
@@ -364,11 +358,9 @@
horizontalMargin = displayOption.horizontalMargin;
numShownHotseatIcons = closestProfile.numHotseatIcons;
- numShrunkenHotseatIcons = closestProfile.numShrunkenHotseatIcons;
numDatabaseHotseatIcons = deviceType == TYPE_MULTI_DISPLAY
? closestProfile.numDatabaseHotseatIcons : closestProfile.numHotseatIcons;
hotseatColumnSpan = closestProfile.hotseatColumnSpan;
- hotseatBorderSpaces = displayOption.hotseatBorderSpaces;
hotseatBarBottomSpace = displayOption.hotseatBarBottomSpace;
hotseatQsbSpace = displayOption.hotseatQsbSpace;
@@ -737,7 +729,6 @@
private final int numAllAppsColumns;
private final int numDatabaseAllAppsColumns;
private final int numHotseatIcons;
- private final int numShrunkenHotseatIcons;
private final int numDatabaseHotseatIcons;
private final int[] hotseatColumnSpan = new int[COUNT_SIZES];
@@ -777,8 +768,6 @@
numHotseatIcons = a.getInt(
R.styleable.GridDisplayOption_numHotseatIcons, numColumns);
- numShrunkenHotseatIcons = a.getInt(
- R.styleable.GridDisplayOption_numShrunkenHotseatIcons, numHotseatIcons / 2);
numDatabaseHotseatIcons = a.getInt(
R.styleable.GridDisplayOption_numExtendedHotseatIcons, 2 * numHotseatIcons);
@@ -842,8 +831,6 @@
private float folderBorderSpace;
private final PointF[] borderSpaces = new PointF[COUNT_SIZES];
private final float[] horizontalMargin = new float[COUNT_SIZES];
- //TODO(http://b/228998082) remove this when 3 button spaces are fixed
- private final float[] hotseatBorderSpaces = new float[COUNT_SIZES];
private final float[] hotseatBarBottomSpace = new float[COUNT_SIZES];
private final float[] hotseatQsbSpace = new float[COUNT_SIZES];
@@ -1059,18 +1046,6 @@
R.styleable.ProfileDisplayOption_horizontalMarginTwoPanelPortrait,
horizontalMargin[INDEX_DEFAULT]);
- hotseatBorderSpaces[INDEX_DEFAULT] = a.getFloat(
- R.styleable.ProfileDisplayOption_hotseatBorderSpace, borderSpace);
- hotseatBorderSpaces[INDEX_LANDSCAPE] = a.getFloat(
- R.styleable.ProfileDisplayOption_hotseatBorderSpaceLandscape,
- hotseatBorderSpaces[INDEX_DEFAULT]);
- hotseatBorderSpaces[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
- R.styleable.ProfileDisplayOption_hotseatBorderSpaceTwoPanelLandscape,
- hotseatBorderSpaces[INDEX_DEFAULT]);
- hotseatBorderSpaces[INDEX_TWO_PANEL_PORTRAIT] = a.getFloat(
- R.styleable.ProfileDisplayOption_hotseatBorderSpaceTwoPanelPortrait,
- hotseatBorderSpaces[INDEX_DEFAULT]);
-
hotseatBarBottomSpace[INDEX_DEFAULT] = a.getFloat(
R.styleable.ProfileDisplayOption_hotseatBarBottomSpace,
ResourcesCompat.getFloat(context.getResources(),
@@ -1133,7 +1108,6 @@
minCellSize[i].x *= w;
minCellSize[i].y *= w;
horizontalMargin[i] *= w;
- hotseatBorderSpaces[i] *= w;
hotseatBarBottomSpace[i] *= w;
hotseatQsbSpace[i] *= w;
allAppsCellSize[i].x *= w;
@@ -1158,7 +1132,6 @@
minCellSize[i].x += p.minCellSize[i].x;
minCellSize[i].y += p.minCellSize[i].y;
horizontalMargin[i] += p.horizontalMargin[i];
- hotseatBorderSpaces[i] += p.hotseatBorderSpaces[i];
hotseatBarBottomSpace[i] += p.hotseatBarBottomSpace[i];
hotseatQsbSpace[i] += p.hotseatQsbSpace[i];
allAppsCellSize[i].x += p.allAppsCellSize[i].x;