Adjust edit state drop targets and workspace scaling per device type and orientation.
This is a partial revert of ag/17540098
Bug: 202971709
Test: manual
Change-Id: I0a642f932afd75e47ce11a2c1ee94643d1a67e0c
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 3489c31..67d6f40 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -108,7 +108,8 @@
public final int cellLayoutPaddingLeftRightPx;
public final int cellLayoutBottomPaddingPx;
public final int edgeMarginPx;
- public float workspaceSpringLoadShrinkFactor;
+ public float workspaceSpringLoadShrunkTop;
+ public float workspaceSpringLoadShrunkBottom;
public final int workspaceSpringLoadedBottomSpace;
private final int extraSpace;
@@ -164,6 +165,7 @@
public int hotseatBarSizePx;
public int hotseatBarTopPaddingPx;
public final int hotseatBarBottomPaddingPx;
+ public int springLoadedHotseatBarTopMarginPx;
// Start is the side next to the nav bar, end is the side next to the workspace
public final int hotseatBarSidePaddingStartPx;
public final int hotseatBarSidePaddingEndPx;
@@ -209,8 +211,13 @@
// Drop Target
public int dropTargetBarSizePx;
+ public int dropTargetBarTopMarginPx;
+ public int dropTargetBarBottomMarginPx;
public int dropTargetDragPaddingPx;
public int dropTargetTextSizePx;
+ public int dropTargetHorizontalPaddingPx;
+ public int dropTargetVerticalPaddingPx;
+ public int dropTargetGapPx;
// Insets
private final Rect mInsets = new Rect();
@@ -347,8 +354,15 @@
res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
dropTargetBarSizePx = res.getDimensionPixelSize(R.dimen.dynamic_grid_drop_target_size);
+ dropTargetBarTopMarginPx = res.getDimensionPixelSize(R.dimen.drop_target_top_margin);
+ dropTargetBarBottomMarginPx = res.getDimensionPixelSize(R.dimen.drop_target_bottom_margin);
dropTargetDragPaddingPx = res.getDimensionPixelSize(R.dimen.drop_target_drag_padding);
dropTargetTextSizePx = res.getDimensionPixelSize(R.dimen.drop_target_text_size);
+ dropTargetHorizontalPaddingPx = res.getDimensionPixelSize(
+ R.dimen.drop_target_button_drawable_horizontal_padding);
+ dropTargetVerticalPaddingPx = res.getDimensionPixelSize(
+ R.dimen.drop_target_button_drawable_vertical_padding);
+ dropTargetGapPx = res.getDimensionPixelSize(R.dimen.drop_target_button_gap);
workspaceSpringLoadedBottomSpace =
res.getDimensionPixelSize(R.dimen.dynamic_grid_min_spring_loaded_space);
@@ -389,6 +403,8 @@
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
qsbWidth = 0;
}
+ springLoadedHotseatBarTopMarginPx = res.getDimensionPixelSize(
+ R.dimen.spring_loaded_hotseat_top_margin);
hotseatBarSidePaddingEndPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_side_padding);
// Add a bit of space between nav bar and hotseat in vertical bar layout.
@@ -744,18 +760,6 @@
}
updateHotseatIconSize(iconSizePx);
- if (!isVerticalLayout) {
- int expectedWorkspaceHeight = availableHeightPx - hotseatBarSizePx
- - workspacePageIndicatorHeight - edgeMarginPx;
- float minRequiredHeight = dropTargetBarSizePx + workspaceSpringLoadedBottomSpace;
- workspaceSpringLoadShrinkFactor = Math.min(
- res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f,
- 1 - (minRequiredHeight / expectedWorkspaceHeight));
- } else {
- workspaceSpringLoadShrinkFactor =
- res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
- }
-
// Folder icon
folderIconSizePx = IconNormalizer.getNormalizedCircleSize(iconSizePx);
folderIconOffsetYPx = (iconSizePx - folderIconSizePx) / 2;
@@ -897,6 +901,41 @@
return result;
}
+ /**
+ * Gets the space in px from the bottom of last item in the vertical-bar hotseat to the
+ * bottom of the screen.
+ */
+ public int getVerticalHotseatLastItemBottomOffset() {
+ int cellHeight = calculateCellHeight(
+ heightPx - mHotseatPadding.top - mHotseatPadding.bottom, hotseatBorderSpace,
+ numShownHotseatIcons);
+ int hotseatSize = (cellHeight * numShownHotseatIcons)
+ + (hotseatBorderSpace * (numShownHotseatIcons - 1));
+ int extraHotseatEndSpacing = (heightPx - hotseatSize) / 2;
+ int extraIconEndSpacing = (cellHeight - iconSizePx) / 2;
+ return extraHotseatEndSpacing + extraIconEndSpacing + mHotseatPadding.bottom;
+ }
+
+ /**
+ * Gets the scaled top of the workspace in px for the spring-loaded edit state.
+ */
+ public float getWorkspaceSpringLoadShrunkTop() {
+ workspaceSpringLoadShrunkTop = mInsets.top + dropTargetBarTopMarginPx + dropTargetBarSizePx
+ + dropTargetBarBottomMarginPx;
+ return workspaceSpringLoadShrunkTop;
+ }
+
+ /**
+ * Gets the scaled bottom of the workspace in px for the spring-loaded edit state.
+ */
+ public float getWorkspaceSpringLoadShrunkBottom() {
+ int topOfHotseat = hotseatBarSizePx + springLoadedHotseatBarTopMarginPx;
+ workspaceSpringLoadShrunkBottom =
+ heightPx - (isVerticalBarLayout() ? getVerticalHotseatLastItemBottomOffset()
+ : topOfHotseat);
+ return workspaceSpringLoadShrunkBottom;
+ }
+
public int getWorkspaceWidth() {
return getWorkspaceWidth(getTotalWorkspacePadding());
}
@@ -1206,6 +1245,12 @@
hotseatBarSidePaddingStartPx));
writer.println(prefix + pxToDpStr("hotseatBarSidePaddingEndPx",
hotseatBarSidePaddingEndPx));
+ writer.println(prefix + pxToDpStr("springLoadedHotseatBarTopMarginPx",
+ springLoadedHotseatBarTopMarginPx));
+ writer.println(prefix + pxToDpStr("mHotseatPadding.top", mHotseatPadding.top));
+ writer.println(prefix + pxToDpStr("mHotseatPadding.bottom", mHotseatPadding.bottom));
+ writer.println(prefix + pxToDpStr("mHotseatPadding.left", mHotseatPadding.left));
+ writer.println(prefix + pxToDpStr("mHotseatPadding.right", mHotseatPadding.right));
writer.println(prefix + "\tnumShownHotseatIcons: " + numShownHotseatIcons);
writer.println(prefix + pxToDpStr("hotseatBorderSpace", hotseatBorderSpace));
writer.println(prefix + "\tisQsbInline: " + isQsbInline);
@@ -1256,6 +1301,16 @@
writer.println(prefix + pxToDpStr("overviewPageSpacing", overviewPageSpacing));
writer.println(prefix + pxToDpStr("overviewRowSpacing", overviewRowSpacing));
writer.println(prefix + pxToDpStr("overviewGridSideMargin", overviewGridSideMargin));
+
+ writer.println(prefix + pxToDpStr("dropTargetBarTopMarginPx", dropTargetBarTopMarginPx));
+ writer.println(prefix + pxToDpStr("dropTargetBarSizePx", dropTargetBarSizePx));
+ writer.println(
+ prefix + pxToDpStr("dropTargetBarBottomMarginPx", dropTargetBarBottomMarginPx));
+
+ writer.println(
+ prefix + pxToDpStr("workspaceSpringLoadShrunkTop", workspaceSpringLoadShrunkTop));
+ writer.println(prefix + pxToDpStr("workspaceSpringLoadShrunkBottom",
+ workspaceSpringLoadShrunkBottom));
}
private static Context getContext(Context c, Info info, int orientation, WindowBounds bounds) {
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index 9fb14f6..73289fb 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -17,8 +17,6 @@
package com.android.launcher3;
import static com.android.launcher3.ButtonDropTarget.TOOLTIP_DEFAULT;
-import static com.android.launcher3.ButtonDropTarget.TOOLTIP_LEFT;
-import static com.android.launcher3.ButtonDropTarget.TOOLTIP_RIGHT;
import static com.android.launcher3.anim.AlphaUpdateListener.updateVisibility;
import android.animation.TimeInterpolator;
@@ -41,6 +39,8 @@
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.testing.TestProtocol;
+import java.util.Arrays;
+
/*
* The top bar containing various drop targets: Delete/App Info/Uninstall.
*/
@@ -94,30 +94,28 @@
lp.rightMargin = insets.right;
int tooltipLocation = TOOLTIP_DEFAULT;
- if (grid.isVerticalBarLayout()) {
- lp.width = grid.dropTargetBarSizePx;
- lp.height = grid.availableHeightPx - 2 * grid.edgeMarginPx;
- lp.gravity = grid.isSeascape() ? Gravity.RIGHT : Gravity.LEFT;
- tooltipLocation = grid.isSeascape() ? TOOLTIP_LEFT : TOOLTIP_RIGHT;
+ int horizontalMargin;
+ if (grid.isTablet) {
+ // XXX: If the icon size changes across orientations, we will have to take
+ // that into account here too.
+ horizontalMargin = ((grid.widthPx - 2 * grid.edgeMarginPx
+ - (grid.inv.numColumns * grid.cellWidthPx))
+ / (2 * (grid.inv.numColumns + 1)))
+ + grid.edgeMarginPx;
} else {
- int gap;
- if (grid.isTablet) {
- // XXX: If the icon size changes across orientations, we will have to take
- // that into account here too.
- gap = ((grid.widthPx - 2 * grid.edgeMarginPx
- - (grid.inv.numColumns * grid.cellWidthPx))
- / (2 * (grid.inv.numColumns + 1)))
- + grid.edgeMarginPx;
- } else {
- gap = getContext().getResources()
- .getDimensionPixelSize(R.dimen.drop_target_bar_margin_horizontal);
- }
- lp.width = grid.availableWidthPx - 2 * gap;
-
- lp.topMargin += grid.edgeMarginPx;
- lp.height = grid.dropTargetBarSizePx;
- lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
+ horizontalMargin = getContext().getResources()
+ .getDimensionPixelSize(R.dimen.drop_target_bar_margin_horizontal);
}
+ lp.topMargin += grid.dropTargetBarTopMarginPx;
+ lp.bottomMargin += grid.dropTargetBarBottomMarginPx;
+ lp.width = grid.availableWidthPx - 2 * horizontalMargin;
+ if (mIsVertical) {
+ lp.leftMargin = (grid.widthPx - lp.width) / 2;
+ lp.rightMargin = (grid.widthPx - lp.width) / 2;
+ }
+ lp.height = grid.dropTargetBarSizePx;
+ lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
+
setLayoutParams(lp);
for (ButtonDropTarget button : mDropTargets) {
button.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.dropTargetTextSizePx);
@@ -139,19 +137,7 @@
int height = MeasureSpec.getSize(heightMeasureSpec);
int visibleCount = getVisibleButtonsCount();
- if (visibleCount == 0) {
- // do nothing
- } else if (mIsVertical) {
- int widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
- int heightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
-
- for (ButtonDropTarget button : mDropTargets) {
- if (button.getVisibility() != GONE) {
- button.setTextVisible(false);
- button.measure(widthSpec, heightSpec);
- }
- }
- } else {
+ if (visibleCount > 0) {
int availableWidth = width / visibleCount;
boolean textVisible = true;
for (ButtonDropTarget buttons : mDropTargets) {
@@ -176,31 +162,91 @@
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int visibleCount = getVisibleButtonsCount();
if (visibleCount == 0) {
- // do nothing
- } else if (mIsVertical) {
- int gap = getResources().getDimensionPixelSize(R.dimen.drop_target_vertical_gap);
- int start = gap;
- int end;
+ return;
+ }
- for (ButtonDropTarget button : mDropTargets) {
- if (button.getVisibility() != GONE) {
- end = start + button.getMeasuredHeight();
- button.layout(0, start, button.getMeasuredWidth(), end);
- start = end + gap;
- }
- }
- } else {
- int frameSize = (right - left) / visibleCount;
+ Launcher launcher = Launcher.getLauncher(getContext());
+ Workspace workspace = launcher.getWorkspace();
+ DeviceProfile dp = launcher.getDeviceProfile();
+ int buttonHorizontalPadding = dp.dropTargetHorizontalPaddingPx;
+ int buttonVerticalPadding = dp.dropTargetVerticalPaddingPx;
+ int barCenter = (right - left) / 2;
- int start = frameSize / 2;
- int halfWidth;
- for (ButtonDropTarget button : mDropTargets) {
- if (button.getVisibility() != GONE) {
- halfWidth = button.getMeasuredWidth() / 2;
- button.layout(start - halfWidth, 0,
- start + halfWidth, button.getMeasuredHeight());
- start = start + frameSize;
+ ButtonDropTarget[] visibleButtons = Arrays.stream(mDropTargets)
+ .filter(b -> b.getVisibility() != GONE)
+ .toArray(ButtonDropTarget[]::new);
+ Arrays.stream(visibleButtons).forEach(
+ b -> b.setPadding(buttonHorizontalPadding, buttonVerticalPadding,
+ buttonHorizontalPadding, buttonVerticalPadding));
+
+ if (visibleCount == 1) {
+ ButtonDropTarget button = visibleButtons[0];
+ button.layout(barCenter - (button.getMeasuredWidth() / 2), 0,
+ barCenter + (button.getMeasuredWidth() / 2), button.getMeasuredHeight());
+ } else if (visibleCount == 2) {
+ int buttonGap = dp.dropTargetGapPx;
+
+ if (dp.isTwoPanels) {
+ ButtonDropTarget leftButton = visibleButtons[0];
+ leftButton.layout(barCenter - leftButton.getMeasuredWidth() - (buttonGap / 2), 0,
+ barCenter - (buttonGap / 2), leftButton.getMeasuredHeight());
+
+ ButtonDropTarget rightButton = visibleButtons[1];
+ rightButton.layout(barCenter + (buttonGap / 2), 0,
+ barCenter + rightButton.getMeasuredWidth() + (buttonGap / 2),
+ rightButton.getMeasuredHeight());
+ } else if (dp.isTablet) {
+ int numberOfMargins = visibleCount - 1;
+ int buttonWidths = Arrays.stream(mDropTargets)
+ .filter(b -> b.getVisibility() != GONE)
+ .mapToInt(ButtonDropTarget::getMeasuredWidth)
+ .sum();
+ int totalWidth = buttonWidths + (numberOfMargins * buttonGap);
+ int buttonsStartMargin = barCenter - (totalWidth / 2);
+
+ int start = buttonsStartMargin;
+ for (ButtonDropTarget button : visibleButtons) {
+ int margin = (start != buttonsStartMargin) ? buttonGap : 0;
+ button.layout(start + margin, 0, start + margin + button.getMeasuredWidth(),
+ button.getMeasuredHeight());
+ start += button.getMeasuredWidth() + margin;
}
+ } else if (mIsVertical) {
+ // Center buttons over workspace, not screen.
+ int verticalCenter = (workspace.getRight() - workspace.getLeft()) / 2;
+ ButtonDropTarget leftButton = visibleButtons[0];
+ leftButton.layout(verticalCenter - leftButton.getMeasuredWidth() - (buttonGap / 2),
+ 0, verticalCenter - (buttonGap / 2), leftButton.getMeasuredHeight());
+
+ ButtonDropTarget rightButton = visibleButtons[1];
+ rightButton.layout(verticalCenter + (buttonGap / 2), 0,
+ verticalCenter + rightButton.getMeasuredWidth() + (buttonGap / 2),
+ rightButton.getMeasuredHeight());
+ } else if (dp.isPhone) {
+ // Buttons aligned to outer edges of scaled workspace.
+ float shrunkTop = dp.getWorkspaceSpringLoadShrunkTop();
+ float shrunkBottom = dp.getWorkspaceSpringLoadShrunkBottom();
+ float scale =
+ (shrunkBottom - shrunkTop) / launcher.getWorkspace().getNormalChildHeight();
+ int workspaceWidth = (int) (launcher.getWorkspace().getNormalChildWidth() * scale);
+ int start = barCenter - (workspaceWidth / 2);
+ int end = barCenter + (workspaceWidth / 2);
+
+ ButtonDropTarget leftButton = visibleButtons[0];
+ ButtonDropTarget rightButton = visibleButtons[1];
+
+ // If the text within the buttons is too long, the buttons can overlap
+ int overlap = start + leftButton.getMeasuredWidth() + rightButton.getMeasuredWidth()
+ - end;
+ if (overlap > 0) {
+ start -= overlap / 2;
+ end += overlap / 2;
+ }
+
+ leftButton.layout(start, 0, start + leftButton.getMeasuredWidth(),
+ leftButton.getMeasuredHeight());
+ rightButton.layout(end - rightButton.getMeasuredWidth(), 0, end,
+ rightButton.getMeasuredHeight());
}
}
}
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index d52594e..9be3cc5 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import android.content.Context;
-import android.graphics.Rect;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
@@ -52,28 +51,15 @@
return super.getWorkspaceScaleAndTranslation(launcher);
}
- if (grid.isVerticalBarLayout()) {
- float scale = grid.workspaceSpringLoadShrinkFactor;
- return new ScaleAndTranslation(scale, 0, 0);
- }
-
- float scale = grid.workspaceSpringLoadShrinkFactor;
- Rect insets = launcher.getDragLayer().getInsets();
-
- float scaledHeight = scale * ws.getNormalChildHeight();
- float shrunkTop = insets.top + grid.dropTargetBarSizePx;
- float shrunkBottom = ws.getMeasuredHeight() - insets.bottom
- - grid.workspacePadding.bottom
- - grid.workspaceSpringLoadedBottomSpace;
- float totalShrunkSpace = shrunkBottom - shrunkTop;
-
- float desiredCellTop = shrunkTop + (totalShrunkSpace - scaledHeight) / 2;
+ float shrunkTop = grid.getWorkspaceSpringLoadShrunkTop();
+ float shrunkBottom = grid.getWorkspaceSpringLoadShrunkBottom();
+ float scale = (shrunkBottom - shrunkTop) / ws.getNormalChildHeight();
float halfHeight = ws.getHeight() / 2;
float myCenter = ws.getTop() + halfHeight;
float cellTopFromCenter = halfHeight - ws.getChildAt(0).getTop();
float actualCellTop = myCenter - cellTopFromCenter * scale;
- return new ScaleAndTranslation(scale, 0, (desiredCellTop - actualCellTop) / scale);
+ return new ScaleAndTranslation(scale, 0, (shrunkTop - actualCellTop) / scale);
}
@Override