Loading robolectric_tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java +43 −0 Original line number Diff line number Diff line Loading @@ -20,8 +20,10 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; import android.appwidget.AppWidgetHostView; import android.content.Context; import android.graphics.Point; import android.graphics.Rect; import com.android.launcher3.DeviceProfile; import com.android.launcher3.InvariantDeviceProfile; Loading Loading @@ -110,6 +112,47 @@ public final class LauncherAppWidgetProviderInfoTest { assertThat(info.minSpanY).isEqualTo(2); } @Test public void initSpans_minResizeWidthWithCellSpacingAndWidgetInset_shouldInitializeMinSpans() { InvariantDeviceProfile idp = createIDP(); DeviceProfile dp = idp.supportedProfiles.get(0); Rect padding = new Rect(); AppWidgetHostView.getDefaultPaddingForWidget(mContext, null, padding); int maxPadding = Math.max(Math.max(padding.left, padding.right), Math.max(padding.top, padding.bottom)); dp.cellLayoutBorderSpacingPx = maxPadding + 1; Mockito.when(dp.shouldInsetWidgets()).thenReturn(true); LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo(); info.minResizeWidth = CELL_SIZE * 2 + maxPadding; info.minResizeHeight = CELL_SIZE * 2 + maxPadding; info.initSpans(mContext, idp); assertThat(info.minSpanX).isEqualTo(2); assertThat(info.minSpanY).isEqualTo(2); } @Test public void initSpans_minResizeWidthWithCellSpacingAndNoWidgetInset_shouldInitializeMinSpans() { InvariantDeviceProfile idp = createIDP(); DeviceProfile dp = idp.supportedProfiles.get(0); Rect padding = new Rect(); AppWidgetHostView.getDefaultPaddingForWidget(mContext, null, padding); int maxPadding = Math.max(Math.max(padding.left, padding.right), Math.max(padding.top, padding.bottom)); dp.cellLayoutBorderSpacingPx = maxPadding - 1; Mockito.when(dp.shouldInsetWidgets()).thenReturn(false); LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo(); info.minResizeWidth = CELL_SIZE * 2 + maxPadding; info.minResizeHeight = CELL_SIZE * 2 + maxPadding; info.initSpans(mContext, idp); assertThat(info.minSpanX).isEqualTo(3); assertThat(info.minSpanY).isEqualTo(3); } private InvariantDeviceProfile createIDP() { DeviceProfile profile = Mockito.mock(DeviceProfile.class); doAnswer(i -> { Loading src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java +66 −41 Original line number Diff line number Diff line Loading @@ -67,61 +67,86 @@ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo } public void initSpans(Context context, InvariantDeviceProfile idp) { // Always assume we're working with the smallest span to make sure we // reserve enough space in both orientations. float smallestCellWidth = Float.MAX_VALUE; float smallestCellHeight = Float.MAX_VALUE; int minSpanX = 0; int minSpanY = 0; int maxSpanX = idp.numColumns; int maxSpanY = idp.numRows; int spanX = 0; int spanY = 0; Rect widgetPadding = new Rect(); Rect localPadding = new Rect(); AppWidgetHostView.getDefaultPaddingForWidget(context, provider, widgetPadding); Point cellSize = new Point(); boolean isWidgetPadded = false; for (DeviceProfile dp : idp.supportedProfiles) { dp.getCellSize(cellSize); smallestCellWidth = Math.min(smallestCellWidth, cellSize.x); smallestCellHeight = Math.min(smallestCellHeight, cellSize.y); isWidgetPadded = isWidgetPadded || !dp.shouldInsetWidgets(); } // We want to account for the extra amount of padding that we are adding to the widget // to ensure that it gets the full amount of space that it has requested. // If grids supports insetting widgets, we do not account for widget padding. Rect widgetPadding = new Rect(); if (isWidgetPadded) { AppWidgetHostView.getDefaultPaddingForWidget(context, provider, widgetPadding); if (dp.shouldInsetWidgets()) { localPadding.setEmpty(); } else { localPadding.set(widgetPadding); } minSpanX = Math.max(minSpanX, getSpanX(localPadding, minResizeWidth, dp.cellLayoutBorderSpacingPx, cellSize.x)); minSpanY = Math.max(minSpanY, getSpanY(localPadding, minResizeHeight, dp.cellLayoutBorderSpacingPx, cellSize.y)); minSpanX = getSpanX(widgetPadding, minResizeWidth, smallestCellWidth); minSpanY = getSpanY(widgetPadding, minResizeHeight, smallestCellHeight); if (ATLEAST_S) { if (maxResizeWidth > 0) { maxSpanX = Math.min(maxSpanX, getSpanX(localPadding, maxResizeWidth, dp.cellLayoutBorderSpacingPx, cellSize.x)); } if (maxResizeHeight > 0) { maxSpanY = Math.min(maxSpanY, getSpanY(localPadding, maxResizeHeight, dp.cellLayoutBorderSpacingPx, cellSize.y)); } } spanX = Math.max(spanX, getSpanX(localPadding, minWidth, dp.cellLayoutBorderSpacingPx, cellSize.x)); spanY = Math.max(spanY, getSpanY(localPadding, minHeight, dp.cellLayoutBorderSpacingPx, cellSize.y)); } // Use maxResizeWidth/Height if they are defined and we're on S or above. maxSpanX = (ATLEAST_S && maxResizeWidth > 0) ? getSpanX(widgetPadding, maxResizeWidth, smallestCellWidth) : idp.numColumns; maxSpanY = (ATLEAST_S && maxResizeHeight > 0) ? getSpanY(widgetPadding, maxResizeHeight, smallestCellHeight) : idp.numRows; if (ATLEAST_S) { // Ensures maxSpan >= minSpan maxSpanX = Math.max(maxSpanX, minSpanX); maxSpanY = Math.max(maxSpanY, minSpanY); // Use targetCellWidth/Height if it is within the min/max ranges and we're on S or above. // Otherwise, fall back to minWidth/Height. if (ATLEAST_S && targetCellWidth >= minSpanX && targetCellWidth <= maxSpanX // Use targetCellWidth/Height if it is within the min/max ranges. // Otherwise, use the span of minWidth/Height. if (targetCellWidth >= minSpanX && targetCellWidth <= maxSpanX && targetCellHeight >= minSpanY && targetCellHeight <= maxSpanY) { spanX = targetCellWidth; spanY = targetCellHeight; } else { spanX = getSpanX(widgetPadding, minWidth, smallestCellWidth); spanY = getSpanY(widgetPadding, minHeight, smallestCellHeight); } } private int getSpanX(Rect widgetPadding, int widgetWidth, float cellWidth) { this.minSpanX = minSpanX; this.minSpanY = minSpanY; this.maxSpanX = maxSpanX; this.maxSpanY = maxSpanY; this.spanX = spanX; this.spanY = spanY; } private int getSpanX(Rect widgetPadding, int widgetWidth, int cellSpacing, float cellWidth) { return Math.max(1, (int) Math.ceil( (widgetWidth + widgetPadding.left + widgetPadding.right) / cellWidth)); (widgetWidth + widgetPadding.left + widgetPadding.right + cellSpacing) / (cellWidth + cellSpacing))); } private int getSpanY(Rect widgetPadding, int widgetHeight, float cellHeight) { private int getSpanY(Rect widgetPadding, int widgetHeight, int cellSpacing, float cellHeight) { return Math.max(1, (int) Math.ceil( (widgetHeight + widgetPadding.top + widgetPadding.bottom) / cellHeight)); (widgetHeight + widgetPadding.top + widgetPadding.bottom + cellSpacing) / ( cellHeight + cellSpacing))); } public String getLabel(PackageManager packageManager) { Loading Loading
robolectric_tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java +43 −0 Original line number Diff line number Diff line Loading @@ -20,8 +20,10 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; import android.appwidget.AppWidgetHostView; import android.content.Context; import android.graphics.Point; import android.graphics.Rect; import com.android.launcher3.DeviceProfile; import com.android.launcher3.InvariantDeviceProfile; Loading Loading @@ -110,6 +112,47 @@ public final class LauncherAppWidgetProviderInfoTest { assertThat(info.minSpanY).isEqualTo(2); } @Test public void initSpans_minResizeWidthWithCellSpacingAndWidgetInset_shouldInitializeMinSpans() { InvariantDeviceProfile idp = createIDP(); DeviceProfile dp = idp.supportedProfiles.get(0); Rect padding = new Rect(); AppWidgetHostView.getDefaultPaddingForWidget(mContext, null, padding); int maxPadding = Math.max(Math.max(padding.left, padding.right), Math.max(padding.top, padding.bottom)); dp.cellLayoutBorderSpacingPx = maxPadding + 1; Mockito.when(dp.shouldInsetWidgets()).thenReturn(true); LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo(); info.minResizeWidth = CELL_SIZE * 2 + maxPadding; info.minResizeHeight = CELL_SIZE * 2 + maxPadding; info.initSpans(mContext, idp); assertThat(info.minSpanX).isEqualTo(2); assertThat(info.minSpanY).isEqualTo(2); } @Test public void initSpans_minResizeWidthWithCellSpacingAndNoWidgetInset_shouldInitializeMinSpans() { InvariantDeviceProfile idp = createIDP(); DeviceProfile dp = idp.supportedProfiles.get(0); Rect padding = new Rect(); AppWidgetHostView.getDefaultPaddingForWidget(mContext, null, padding); int maxPadding = Math.max(Math.max(padding.left, padding.right), Math.max(padding.top, padding.bottom)); dp.cellLayoutBorderSpacingPx = maxPadding - 1; Mockito.when(dp.shouldInsetWidgets()).thenReturn(false); LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo(); info.minResizeWidth = CELL_SIZE * 2 + maxPadding; info.minResizeHeight = CELL_SIZE * 2 + maxPadding; info.initSpans(mContext, idp); assertThat(info.minSpanX).isEqualTo(3); assertThat(info.minSpanY).isEqualTo(3); } private InvariantDeviceProfile createIDP() { DeviceProfile profile = Mockito.mock(DeviceProfile.class); doAnswer(i -> { Loading
src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java +66 −41 Original line number Diff line number Diff line Loading @@ -67,61 +67,86 @@ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo } public void initSpans(Context context, InvariantDeviceProfile idp) { // Always assume we're working with the smallest span to make sure we // reserve enough space in both orientations. float smallestCellWidth = Float.MAX_VALUE; float smallestCellHeight = Float.MAX_VALUE; int minSpanX = 0; int minSpanY = 0; int maxSpanX = idp.numColumns; int maxSpanY = idp.numRows; int spanX = 0; int spanY = 0; Rect widgetPadding = new Rect(); Rect localPadding = new Rect(); AppWidgetHostView.getDefaultPaddingForWidget(context, provider, widgetPadding); Point cellSize = new Point(); boolean isWidgetPadded = false; for (DeviceProfile dp : idp.supportedProfiles) { dp.getCellSize(cellSize); smallestCellWidth = Math.min(smallestCellWidth, cellSize.x); smallestCellHeight = Math.min(smallestCellHeight, cellSize.y); isWidgetPadded = isWidgetPadded || !dp.shouldInsetWidgets(); } // We want to account for the extra amount of padding that we are adding to the widget // to ensure that it gets the full amount of space that it has requested. // If grids supports insetting widgets, we do not account for widget padding. Rect widgetPadding = new Rect(); if (isWidgetPadded) { AppWidgetHostView.getDefaultPaddingForWidget(context, provider, widgetPadding); if (dp.shouldInsetWidgets()) { localPadding.setEmpty(); } else { localPadding.set(widgetPadding); } minSpanX = Math.max(minSpanX, getSpanX(localPadding, minResizeWidth, dp.cellLayoutBorderSpacingPx, cellSize.x)); minSpanY = Math.max(minSpanY, getSpanY(localPadding, minResizeHeight, dp.cellLayoutBorderSpacingPx, cellSize.y)); minSpanX = getSpanX(widgetPadding, minResizeWidth, smallestCellWidth); minSpanY = getSpanY(widgetPadding, minResizeHeight, smallestCellHeight); if (ATLEAST_S) { if (maxResizeWidth > 0) { maxSpanX = Math.min(maxSpanX, getSpanX(localPadding, maxResizeWidth, dp.cellLayoutBorderSpacingPx, cellSize.x)); } if (maxResizeHeight > 0) { maxSpanY = Math.min(maxSpanY, getSpanY(localPadding, maxResizeHeight, dp.cellLayoutBorderSpacingPx, cellSize.y)); } } spanX = Math.max(spanX, getSpanX(localPadding, minWidth, dp.cellLayoutBorderSpacingPx, cellSize.x)); spanY = Math.max(spanY, getSpanY(localPadding, minHeight, dp.cellLayoutBorderSpacingPx, cellSize.y)); } // Use maxResizeWidth/Height if they are defined and we're on S or above. maxSpanX = (ATLEAST_S && maxResizeWidth > 0) ? getSpanX(widgetPadding, maxResizeWidth, smallestCellWidth) : idp.numColumns; maxSpanY = (ATLEAST_S && maxResizeHeight > 0) ? getSpanY(widgetPadding, maxResizeHeight, smallestCellHeight) : idp.numRows; if (ATLEAST_S) { // Ensures maxSpan >= minSpan maxSpanX = Math.max(maxSpanX, minSpanX); maxSpanY = Math.max(maxSpanY, minSpanY); // Use targetCellWidth/Height if it is within the min/max ranges and we're on S or above. // Otherwise, fall back to minWidth/Height. if (ATLEAST_S && targetCellWidth >= minSpanX && targetCellWidth <= maxSpanX // Use targetCellWidth/Height if it is within the min/max ranges. // Otherwise, use the span of minWidth/Height. if (targetCellWidth >= minSpanX && targetCellWidth <= maxSpanX && targetCellHeight >= minSpanY && targetCellHeight <= maxSpanY) { spanX = targetCellWidth; spanY = targetCellHeight; } else { spanX = getSpanX(widgetPadding, minWidth, smallestCellWidth); spanY = getSpanY(widgetPadding, minHeight, smallestCellHeight); } } private int getSpanX(Rect widgetPadding, int widgetWidth, float cellWidth) { this.minSpanX = minSpanX; this.minSpanY = minSpanY; this.maxSpanX = maxSpanX; this.maxSpanY = maxSpanY; this.spanX = spanX; this.spanY = spanY; } private int getSpanX(Rect widgetPadding, int widgetWidth, int cellSpacing, float cellWidth) { return Math.max(1, (int) Math.ceil( (widgetWidth + widgetPadding.left + widgetPadding.right) / cellWidth)); (widgetWidth + widgetPadding.left + widgetPadding.right + cellSpacing) / (cellWidth + cellSpacing))); } private int getSpanY(Rect widgetPadding, int widgetHeight, float cellHeight) { private int getSpanY(Rect widgetPadding, int widgetHeight, int cellSpacing, float cellHeight) { return Math.max(1, (int) Math.ceil( (widgetHeight + widgetPadding.top + widgetPadding.bottom) / cellHeight)); (widgetHeight + widgetPadding.top + widgetPadding.bottom + cellSpacing) / ( cellHeight + cellSpacing))); } public String getLabel(PackageManager packageManager) { Loading