Merge "Fix hotseat width to span a number of columns" into tm-dev

This commit is contained in:
Thales Lima
2022-05-11 20:56:11 +00:00
committed by Android (Google) Code Review
11 changed files with 103 additions and 48 deletions

View File

@@ -256,7 +256,7 @@ public class TaskIconCache implements DisplayInfoChangeListener {
private BaseIconFactory getIconFactory() {
if (mIconFactory == null) {
mIconFactory = new BaseIconFactory(mContext,
DisplayController.INSTANCE.get(mContext).getInfo().densityDpi,
DisplayController.INSTANCE.get(mContext).getInfo().getDensityDpi(),
mContext.getResources().getDimensionPixelSize(R.dimen.taskbar_icon_size));
}
return mIconFactory;

View File

@@ -159,6 +159,17 @@
defaults to 2 * numHotseatIcons -->
<attr name="numExtendedHotseatIcons" format="integer" />
<!-- alignment of hotseat to the grid.
Not applicable for 3 button mode when taskbar is enabled -->
<!-- defaults to numColumns, if not specified -->
<attr name="hotseatColumnSpan" format="integer" />
<!-- defaults to numColumns, if not specified -->
<attr name="hotseatColumnSpanLandscape" format="integer" />
<!-- defaults to numColumns, if not specified -->
<attr name="hotseatColumnSpanTwoPanelLandscape" format="integer" />
<!-- defaults to numColumns, if not specified -->
<attr name="hotseatColumnSpanTwoPanelPortrait" format="integer" />
<attr name="dbFile" format="string" />
<attr name="defaultLayoutId" format="reference" />
<attr name="defaultSplitDisplayLayoutId" format="reference" />

View File

@@ -144,6 +144,7 @@
launcher:numFolderRows="3"
launcher:numFolderColumns="3"
launcher:numHotseatIcons="6"
launcher:hotseatColumnSpanLandscape="4"
launcher:numAllAppsColumns="6"
launcher:isScalable="true"
launcher:devicePaddingId="@xml/paddings_6x5"

View File

@@ -158,6 +158,7 @@ public class DeviceProfile {
public final int numShownHotseatIcons;
public int hotseatCellHeightPx;
private final int hotseatExtraVerticalSize;
private final boolean areNavButtonsInline;
// In portrait: size = height, in landscape: size = width
public int hotseatBarSizePx;
public int hotseatBarTopPaddingPx;
@@ -358,7 +359,7 @@ public class DeviceProfile {
// 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.
boolean areNavButtonsInline = isTaskbarPresent && !isGestureMode;
areNavButtonsInline = isTaskbarPresent && !isGestureMode;
if (areNavButtonsInline && canQsbInline) {
numShownHotseatIcons = inv.numShrunkenHotseatIcons;
} else {
@@ -373,15 +374,14 @@ public class DeviceProfile {
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding);
if (isQsbInline) {
hotseatBarBottomPaddingPx = res.getDimensionPixelSize(R.dimen.inline_qsb_bottom_margin);
qsbWidth = calculateQsbWidth();
} else {
hotseatBarBottomPaddingPx = (isTallDevice ? res.getDimensionPixelSize(
R.dimen.dynamic_grid_hotseat_bottom_tall_padding)
: res.getDimensionPixelSize(
R.dimen.dynamic_grid_hotseat_bottom_non_tall_padding))
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
qsbWidth = 0;
}
springLoadedHotseatBarTopMarginPx = res.getDimensionPixelSize(
R.dimen.spring_loaded_hotseat_top_margin);
hotseatBarSidePaddingEndPx =
@@ -390,9 +390,7 @@ public class DeviceProfile {
hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
hotseatExtraVerticalSize =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size);
hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
updateHotseatIconSize(
pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
updateHotseatIconSize(pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
qsbBottomMarginOriginalPx = isScalableGrid
? res.getDimensionPixelSize(R.dimen.scalable_grid_qsb_bottom_margin)
@@ -483,6 +481,10 @@ public class DeviceProfile {
cellLayoutPadding);
updateWorkspacePadding();
// Hotseat and QSB width depends on updated cellSize and workspace padding
hotseatBorderSpace = calculateHotseatBorderSpace();
qsbWidth = calculateQsbWidth();
flingToDeleteThresholdVelocity = res.getDimensionPixelSize(
R.dimen.drag_flingToDeleteMinVelocity);
@@ -493,14 +495,26 @@ public class DeviceProfile {
new DotRenderer(allAppsIconSizePx, dotPath, DEFAULT_DOT_SIZE);
}
/**
* QSB width is always calculated because when in 3 button nav the width doesn't follow the
* width of the hotseat.
*/
private int calculateQsbWidth() {
int columns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
if (isQsbInline) {
int columns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
return getIconToIconWidthForColumns(columns)
- iconSizePx * numShownHotseatIcons
- hotseatBorderSpace * numShownHotseatIcons;
} else {
int columns = inv.hotseatColumnSpan[mTypeIndex];
return getIconToIconWidthForColumns(columns);
}
}
return cellWidthPx * columns
+ cellLayoutBorderSpacePx.x * (columns - 1)
- (cellWidthPx - iconSizePx) // left and right cell space
- iconSizePx * numShownHotseatIcons
- hotseatBorderSpace * numShownHotseatIcons;
private int getIconToIconWidthForColumns(int columns) {
return columns * getCellSize().x
+ (columns - 1) * cellLayoutBorderSpacePx.x
- (getCellSize().x - iconSizePx); // left and right cell space
}
private int getHorizontalMarginPx(InvariantDeviceProfile idp, Resources res) {
@@ -741,13 +755,6 @@ public class DeviceProfile {
// All apps
updateAllAppsIconSize(scale, res);
// Hotseat
hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics, scale);
if (isQsbInline) {
qsbWidth = calculateQsbWidth();
} else {
qsbWidth = 0;
}
updateHotseatIconSize(iconSizePx);
// Folder icon
@@ -755,6 +762,23 @@ public class DeviceProfile {
folderIconOffsetYPx = (iconSizePx - folderIconSizePx) / 2;
}
/**
* Hotseat width spans a certain number of columns on scalable grids.
* This method calculates the space between the icons to achieve that width.
*/
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);
}
}
/**
* Updates the iconSize for allApps* variants.
@@ -1070,6 +1094,13 @@ public class DeviceProfile {
mHotseatPadding.left -= diff;
mHotseatPadding.right += diff;
}
} else if (isScalableGrid) {
int sideSpacing = (availableWidthPx - qsbWidth) / 2;
mHotseatPadding.set(sideSpacing,
hotseatBarTopPaddingPx,
sideSpacing,
hotseatBarSizePx - hotseatCellHeightPx - hotseatBarTopPaddingPx
+ mInsets.bottom);
} else {
// We want the edges of the hotseat to line up with the edges of the workspace, but the
// icons in the hotseat are a different size, and so don't line up perfectly. To account
@@ -1306,6 +1337,7 @@ public class DeviceProfile {
writer.println(prefix + pxToDpStr("allAppsLeftRightMargin", allAppsLeftRightMargin));
writer.println(prefix + pxToDpStr("hotseatBarSizePx", hotseatBarSizePx));
writer.println(prefix + "\tinv.hotseatColumnSpan: " + inv.hotseatColumnSpan[mTypeIndex]);
writer.println(prefix + pxToDpStr("hotseatCellHeightPx", hotseatCellHeightPx));
writer.println(prefix + pxToDpStr("hotseatBarTopPaddingPx", hotseatBarTopPaddingPx));
writer.println(prefix + pxToDpStr("hotseatBarBottomPaddingPx", hotseatBarBottomPaddingPx));
@@ -1384,7 +1416,7 @@ public class DeviceProfile {
private static Context getContext(Context c, Info info, int orientation, WindowBounds bounds) {
Configuration config = new Configuration(c.getResources().getConfiguration());
config.orientation = orientation;
config.densityDpi = info.densityDpi;
config.densityDpi = info.getDensityDpi();
config.smallestScreenWidthDp = (int) info.smallestSizeDp(bounds);
return c.createConfigurationContext(config);
}

View File

@@ -173,17 +173,9 @@ public class Hotseat extends CellLayout implements Insettable {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width;
if (mActivity.getDeviceProfile().isQsbInline) {
width = mActivity.getDeviceProfile().qsbWidth;
} else {
MarginLayoutParams qsbParams = (MarginLayoutParams) mQsb.getLayoutParams();
width = getShortcutsAndWidgets().getMeasuredWidth()
- qsbParams.getMarginStart()
- qsbParams.getMarginEnd();
}
int qsbWidth = mActivity.getDeviceProfile().qsbWidth;
mQsb.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
mQsb.measure(MeasureSpec.makeMeasureSpec(qsbWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mQsbHeight, MeasureSpec.EXACTLY));
}

View File

@@ -154,6 +154,8 @@ public class InvariantDeviceProfile {
*/
public int numDatabaseHotseatIcons;
public int[] hotseatColumnSpan;
/**
* Number of columns in the all apps list.
*/
@@ -357,6 +359,7 @@ public class InvariantDeviceProfile {
numShrunkenHotseatIcons = closestProfile.numShrunkenHotseatIcons;
numDatabaseHotseatIcons = deviceType == TYPE_MULTI_DISPLAY
? closestProfile.numDatabaseHotseatIcons : closestProfile.numHotseatIcons;
hotseatColumnSpan = closestProfile.hotseatColumnSpan;
hotseatBorderSpaces = displayOption.hotseatBorderSpaces;
numAllAppsColumns = closestProfile.numAllAppsColumns;
@@ -398,7 +401,8 @@ public class InvariantDeviceProfile {
// We need to ensure that there is enough extra space in the wallpaper
// for the intended parallax effects
float parallaxFactor =
dpiFromPx(Math.min(displayWidth, displayHeight), displayInfo.densityDpi) < 720
dpiFromPx(Math.min(displayWidth, displayHeight), displayInfo.getDensityDpi())
< 720
? 2
: wallpaperTravelToScreenWidthRatio(displayWidth, displayHeight);
defaultWallpaperSize.x =
@@ -587,8 +591,8 @@ public class InvariantDeviceProfile {
}
}
float width = dpiFromPx(minWidthPx, displayInfo.densityDpi);
float height = dpiFromPx(minHeightPx, displayInfo.densityDpi);
float width = dpiFromPx(minWidthPx, displayInfo.getDensityDpi());
float height = dpiFromPx(minHeightPx, displayInfo.getDensityDpi());
// Sort the profiles based on the closeness to the device size
Collections.sort(points, (a, b) ->
@@ -735,6 +739,7 @@ public class InvariantDeviceProfile {
private final int numHotseatIcons;
private final int numShrunkenHotseatIcons;
private final int numDatabaseHotseatIcons;
private final int[] hotseatColumnSpan = new int[COUNT_SIZES];
private final String dbFile;
@@ -774,6 +779,16 @@ public class InvariantDeviceProfile {
R.styleable.GridDisplayOption_numShrunkenHotseatIcons, numHotseatIcons / 2);
numDatabaseHotseatIcons = a.getInt(
R.styleable.GridDisplayOption_numExtendedHotseatIcons, 2 * numHotseatIcons);
hotseatColumnSpan[INDEX_DEFAULT] = a.getInt(
R.styleable.GridDisplayOption_hotseatColumnSpan, numColumns);
hotseatColumnSpan[INDEX_LANDSCAPE] = a.getInt(
R.styleable.GridDisplayOption_hotseatColumnSpanLandscape, numColumns);
hotseatColumnSpan[INDEX_TWO_PANEL_LANDSCAPE] = a.getInt(
R.styleable.GridDisplayOption_hotseatColumnSpanTwoPanelLandscape,
numColumns);
hotseatColumnSpan[INDEX_TWO_PANEL_PORTRAIT] = a.getInt(
R.styleable.GridDisplayOption_hotseatColumnSpanTwoPanelPortrait,
numColumns);
numFolderRows = a.getInt(
R.styleable.GridDisplayOption_numFolderRows, numRows);
@@ -821,6 +836,7 @@ public class InvariantDeviceProfile {
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[] iconSizes = new float[COUNT_SIZES];

View File

@@ -290,7 +290,7 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
// Configuration property
public final float fontScale;
public final int densityDpi;
private final int densityDpi;
public final NavigationMode navigationMode;
private final PortraitSize mScreenSizeDp;
@@ -357,6 +357,10 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
public float smallestSizeDp(WindowBounds bounds) {
return dpiFromPx(Math.min(bounds.bounds.width(), bounds.bounds.height()), densityDpi);
}
public int getDensityDpi() {
return densityDpi;
}
}
/**

View File

@@ -64,6 +64,7 @@ abstract class DeviceProfileBaseTest {
windowBounds = WindowBounds(x, y, x, y - 100, 0)
whenever(info.isTablet(any())).thenReturn(false)
whenever(info.getDensityDpi()).thenReturn(560)
inv = newScalableInvariantDeviceProfile()
}
@@ -77,6 +78,7 @@ abstract class DeviceProfileBaseTest {
windowBounds = WindowBounds(x, y, x, y - 100, 0)
whenever(info.isTablet(any())).thenReturn(true)
whenever(info.getDensityDpi()).thenReturn(320)
inv = newScalableInvariantDeviceProfile()
}
@@ -107,6 +109,7 @@ abstract class DeviceProfileBaseTest {
PointF(16f, 16f)
).toTypedArray()
hotseatBorderSpaces = FloatArray(4) { 16f }
hotseatColumnSpan = IntArray(4) { 4 }
iconSize = FloatArray(4) { 56f }
allAppsIconSize = FloatArray(4) { 56f }
iconTextSize = FloatArray(4) { 14f }

View File

@@ -23,15 +23,13 @@ import com.android.launcher3.InvariantDeviceProfile.TYPE_TABLET
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers
import org.mockito.Mockito.`when` as whenever
/**
* Test for [DeviceProfile]
*/
@SmallTest
@RunWith(AndroidJUnit4::class)
class HotseatSizeTest : DeviceProfileBaseTest() {
class HotseatShownIconsTest : DeviceProfileBaseTest() {
@Test
fun hotseat_size_is_normal_for_handhelds() {

View File

@@ -29,17 +29,16 @@ import org.junit.runner.RunWith
class InlineQsbTest : DeviceProfileBaseTest() {
@Test
fun qsbWidth_is_match_parent_for_phones() {
fun qsb_is_not_inline_for_phones() {
initializeVarsForPhone()
val dp = newDP()
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.qsbWidth).isEqualTo(0)
}
@Test
fun qsbWidth_is_match_parent_for_tablet_portrait() {
fun qsb_is_inline_for_tablet_portrait() {
initializeVarsForTablet()
inv = newScalableInvariantDeviceProfile().apply {
inlineQsb = booleanArrayOf(
@@ -62,11 +61,10 @@ class InlineQsbTest : DeviceProfileBaseTest() {
)
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.qsbWidth).isEqualTo(0)
}
@Test
fun qsbWidth_has_size_for_tablet_landscape() {
fun qsb_is_inline_for_tablet_landscape() {
initializeVarsForTablet(isLandscape = true)
inv = newScalableInvariantDeviceProfile().apply {
inlineQsb = booleanArrayOf(
@@ -75,16 +73,17 @@ class InlineQsbTest : DeviceProfileBaseTest() {
false,
false
)
numColumns = 6
numRows = 5
numShownHotseatIcons = 6
}
val dp = newDP()
if (dp.hotseatQsbHeight > 0) {
assertThat(dp.isQsbInline).isTrue()
assertThat(dp.qsbWidth).isGreaterThan(0)
} else { // Launcher3 doesn't have QSB height
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.qsbWidth).isEqualTo(0)
}
}
@@ -92,14 +91,13 @@ class InlineQsbTest : DeviceProfileBaseTest() {
* This test is to make sure that a tablet doesn't inline the QSB if the layout doesn't support
*/
@Test
fun qsbWidth_is_match_parent_for_tablet_landscape_without_inline() {
fun qsb_is_not_inline_for_tablet_landscape_without_inline() {
initializeVarsForTablet(isLandscape = true)
useTwoPanels = true
val dp = newDP()
assertThat(dp.isQsbInline).isFalse()
assertThat(dp.qsbWidth).isEqualTo(0)
}
}

View File

@@ -135,7 +135,7 @@ public class DeviceEmulationData {
resourceOverrides.put(s, getDimenByName(s, context.getResources(), 0));
}
return new DeviceEmulationData(info.currentSize.x, info.currentSize.y,
info.densityDpi, info.cutout, code, grids, resourceOverrides);
info.getDensityDpi(), info.cutout, code, grids, resourceOverrides);
}
public static DeviceEmulationData getDevice(String deviceCode) throws Exception {