mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-03-03 09:26:51 +00:00
Merge "Fix hotseat width to span a number of columns" into tm-dev
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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() {
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user