From 07b6929cd94e6d55fb660f85baf1df840de48f46 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 8 Jan 2018 14:19:34 -0800 Subject: [PATCH] Removing layout handling in DeviceProfile and moving it to individual views Bug: 71709920 Change-Id: I8300fa7a84b31898bdb135d774cca576d2928525 --- .../com/android/quickstep/RecentsView.java | 2 +- res/layout-land/launcher.xml | 4 +- res/layout-port/launcher.xml | 3 +- res/layout-sw720dp/launcher.xml | 3 +- res/values/config.xml | 4 - src/com/android/launcher3/DeviceProfile.java | 249 ++---------------- src/com/android/launcher3/DropTargetBar.java | 50 +++- src/com/android/launcher3/Hotseat.java | 59 ++++- .../launcher3/InsettableFrameLayout.java | 10 + src/com/android/launcher3/Launcher.java | 8 +- .../android/launcher3/LauncherRootView.java | 19 +- src/com/android/launcher3/Workspace.java | 14 + .../allapps/AllAppsContainerView.java | 45 +--- .../PageIndicatorLandscape.java | 30 ++- .../pageindicators/PageIndicatorLine.java | 19 +- .../launcher3/states/SpringLoadedState.java | 2 +- .../android/launcher3/views/AllAppsScrim.java | 28 +- .../launcher3/widget/WidgetsFullSheet.java | 6 +- .../launcher3/uioverrides/OverviewState.java | 5 +- 19 files changed, 228 insertions(+), 332 deletions(-) diff --git a/quickstep/src/com/android/quickstep/RecentsView.java b/quickstep/src/com/android/quickstep/RecentsView.java index ff90ebe426..e7e794f74b 100644 --- a/quickstep/src/com/android/quickstep/RecentsView.java +++ b/quickstep/src/com/android/quickstep/RecentsView.java @@ -217,7 +217,7 @@ public class RecentsView extends PagedView { DeviceProfile profile = launcher.getDeviceProfile(); Rect stableInsets = new Rect(); WindowManagerWrapper.getInstance().getStableInsets(stableInsets); - Rect padding = profile.getWorkspacePadding(null); + Rect padding = new Rect(profile.workspacePadding); float taskWidth = profile.widthPx - stableInsets.left - stableInsets.right; float taskHeight = profile.heightPx - stableInsets.top - stableInsets.bottom; diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml index 3422a98498..9bd3c672bb 100644 --- a/res/layout-land/launcher.xml +++ b/res/layout-land/launcher.xml @@ -63,9 +63,7 @@ + android:layout_height="match_parent" /> + android:layout_height="match_parent" /> diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml index 047577ba7a..7e6c659ad3 100644 --- a/res/layout-sw720dp/launcher.xml +++ b/res/layout-sw720dp/launcher.xml @@ -56,8 +56,7 @@ + android:layout_height="match_parent" /> 90 - - 17 - 50 diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 52b124955a..75e2f70cab 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -25,24 +25,12 @@ import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; import android.util.DisplayMetrics; -import android.view.Gravity; -import android.view.View; -import android.view.ViewGroup.LayoutParams; -import android.widget.FrameLayout; import com.android.launcher3.CellLayout.ContainerType; -import com.android.launcher3.allapps.AllAppsContainerView; import com.android.launcher3.badge.BadgeRenderer; -import com.android.launcher3.views.AllAppsScrim; - -import java.util.ArrayList; public class DeviceProfile { - public interface LauncherLayoutChangeListener { - void onLauncherLayoutChanged(); - } - public final InvariantDeviceProfile inv; // Device properties @@ -66,20 +54,19 @@ public class DeviceProfile { private static final float TALL_DEVICE_ASPECT_RATIO_THRESHOLD = 2.0f; - // Workspace - private final int desiredWorkspaceLeftRightMarginPx; + public final int desiredWorkspaceLeftRightMarginPx; public final int cellLayoutPaddingLeftRightPx; public final int cellLayoutBottomPaddingPx; public final int edgeMarginPx; public final Rect defaultWidgetPadding; - private final int defaultPageSpacingPx; + public final int defaultPageSpacingPx; private final int topWorkspacePadding; public float workspaceSpringLoadShrinkFactor; public final int workspaceSpringLoadedBottomSpace; // Page indicator - private int pageIndicatorSizePx; + public final int pageIndicatorSizePx; // Workspace icons public int iconSizePx; @@ -109,15 +96,14 @@ public class DeviceProfile { public int hotseatCellHeightPx; // In portrait: size = height, in landscape: size = width public int hotseatBarSizePx; - public int hotseatBarTopPaddingPx; - public int hotseatBarBottomPaddingPx; - public int hotseatBarSidePaddingPx; + public final int hotseatBarTopPaddingPx; + public final int hotseatBarBottomPaddingPx; + public final int hotseatBarSidePaddingPx; // All apps public int allAppsCellHeightPx; public int allAppsNumCols; public int allAppsNumPredictiveCols; - public int allAppsButtonVisualSize; public int allAppsIconSizePx; public int allAppsIconDrawablePaddingPx; public float allAppsIconTextSizePx; @@ -129,10 +115,8 @@ public class DeviceProfile { public int dropTargetBarSizePx; // Insets - private Rect mInsets = new Rect(); - - // Listeners - private ArrayList mListeners = new ArrayList<>(); + private final Rect mInsets = new Rect(); + public final Rect workspacePadding = new Rect(); // Icon badges public BadgeRenderer mBadgeRenderer; @@ -224,8 +208,7 @@ public class DeviceProfile { // Recalculate the available dimensions using the new hotseat size. updateAvailableDimensions(dm, res); } - - computeAllAppsButtonSize(context); + updateWorkspacePadding(); // This is done last, after iconSizePx is calculated above. mBadgeRenderer = new BadgeRenderer(iconSizePx); @@ -254,22 +237,11 @@ public class DeviceProfile { float appWidgetScaleX = (float) profile.getCellSize().x / getCellSize().x; float appWidgetScaleY = (float) profile.getCellSize().y / getCellSize().y; profile.appWidgetScale.set(appWidgetScaleX, appWidgetScaleY); + profile.updateWorkspacePadding(); return profile; } - public void addLauncherLayoutChangedListener(LauncherLayoutChangeListener listener) { - if (!mListeners.contains(listener)) { - mListeners.add(listener); - } - } - - public void removeLauncherLayoutChangedListener(LauncherLayoutChangeListener listener) { - if (mListeners.contains(listener)) { - mListeners.remove(listener); - } - } - /** * Adjusts the profile so that the labels on the Workspace are hidden. * It is important to call this method after the All Apps variables have been set. @@ -288,17 +260,6 @@ public class DeviceProfile { + topBottomPadding * 2; } - /** - * Determine the exact visual footprint of the all apps button, taking into account scaling - * and internal padding of the drawable. - */ - private void computeAllAppsButtonSize(Context context) { - Resources res = context.getResources(); - float padding = res.getInteger(R.integer.config_allAppsButtonPaddingPercent) / 100f; - allAppsButtonVisualSize = (int) (iconSizePx * (1 - padding)) - context.getResources() - .getDimensionPixelSize(R.dimen.all_apps_button_scale_down); - } - private void updateAvailableDimensions(DisplayMetrics dm, Resources res) { updateIconSize(1f, res, dm); @@ -314,7 +275,8 @@ public class DeviceProfile { private void updateIconSize(float scale, Resources res, DisplayMetrics dm) { // Workspace - float invIconSizePx = isVerticalBarLayout() ? inv.landscapeIconSize : inv.iconSize; + final boolean isVerticalLayout = isVerticalBarLayout(); + float invIconSizePx = isVerticalLayout ? inv.landscapeIconSize : inv.iconSize; iconSizePx = (int) (Utilities.pxFromDp(invIconSizePx, dm) * scale); iconTextSizePx = (int) (Utilities.pxFromSp(inv.iconTextSize, dm) * scale); iconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * scale); @@ -322,7 +284,7 @@ public class DeviceProfile { cellHeightPx = iconSizePx + iconDrawablePaddingPx + Utilities.calculateTextHeight(iconTextSizePx); int cellYPadding = (getCellSize().y - cellHeightPx) / 2; - if (iconDrawablePaddingPx > cellYPadding && !isVerticalBarLayout() + if (iconDrawablePaddingPx > cellYPadding && !isVerticalLayout && !inMultiWindowMode()) { // Ensures that the label is closer to its corresponding icon. This is not an issue // with vertical bar layout or multi-window mode since the issue is handled separately @@ -338,18 +300,18 @@ public class DeviceProfile { allAppsIconDrawablePaddingPx = iconDrawablePaddingPx; allAppsCellHeightPx = getCellSize().y; - if (isVerticalBarLayout()) { + if (isVerticalLayout) { // Always hide the Workspace text with vertical bar layout. adjustToHideWorkspaceLabels(); } // Hotseat - if (isVerticalBarLayout()) { + if (isVerticalLayout) { hotseatBarSizePx = iconSizePx; } hotseatCellHeightPx = iconSizePx; - if (!isVerticalBarLayout()) { + if (!isVerticalLayout) { int expectedWorkspaceHeight = availableHeightPx - hotseatBarSizePx - pageIndicatorSizePx - topWorkspacePadding; float minRequiredHeight = dropTargetBarSizePx + workspaceSpringLoadedBottomSpace; @@ -376,15 +338,16 @@ public class DeviceProfile { // Don't let the folder get too close to the edges of the screen. int folderMargin = edgeMarginPx; + Point totalWorkspacePadding = getTotalWorkspacePadding(); // Check if the icons fit within the available height. float usedHeight = folderCellHeightPx * inv.numFolderRows + folderBottomPanelSize; - int maxHeight = availableHeightPx - getTotalWorkspacePadding().y - folderMargin; + int maxHeight = availableHeightPx - totalWorkspacePadding.y - folderMargin; float scaleY = maxHeight / usedHeight; // Check if the icons fit within the available width. float usedWidth = folderCellWidthPx * inv.numFolderColumns; - int maxWidth = availableWidthPx - getTotalWorkspacePadding().x - folderMargin; + int maxWidth = availableWidthPx - totalWorkspacePadding.x - folderMargin; float scaleX = maxWidth / usedWidth; float scale = Math.min(scaleX, scaleY); @@ -410,33 +373,13 @@ public class DeviceProfile { public void updateInsets(Rect insets) { mInsets.set(insets); + updateWorkspacePadding(); } public void updateAppsViewNumCols() { allAppsNumCols = allAppsNumPredictiveCols = inv.numColumns; } - /** Returns the width and height of the search bar, ignoring any padding. */ - public Point getSearchBarDimensForWidgetOpts() { - if (isVerticalBarLayout()) { - return new Point(dropTargetBarSizePx, availableHeightPx - 2 * edgeMarginPx); - } else { - int gap; - if (isTablet) { - // Pad the left and right of the workspace to ensure consistent spacing - // between all icons - // XXX: If the icon size changes across orientations, we will have to take - // that into account here too. - gap = ((widthPx - 2 * edgeMarginPx - - (inv.numColumns * cellWidthPx)) / (2 * (inv.numColumns + 1))) - + edgeMarginPx; - } else { - gap = desiredWorkspaceLeftRightMarginPx - defaultWidgetPadding.right; - } - return new Point(availableWidthPx - 2 * gap, dropTargetBarSizePx); - } - } - public Point getCellSize() { Point result = new Point(); // Since we are only concerned with the overall padding, layout direction does @@ -450,15 +393,17 @@ public class DeviceProfile { } public Point getTotalWorkspacePadding() { - Rect padding = getWorkspacePadding(null); - return new Point(padding.left + padding.right, padding.top + padding.bottom); + updateWorkspacePadding(); + return new Point(workspacePadding.left + workspacePadding.right, + workspacePadding.top + workspacePadding.bottom); } /** - * Returns the workspace padding in the specified orientation. + * Updates {@link #workspacePadding} as a result of any internal value change to reflect the + * new workspace padding */ - public Rect getWorkspacePadding(Rect recycle) { - Rect padding = recycle == null ? new Rect() : recycle; + private void updateWorkspacePadding() { + Rect padding = workspacePadding; if (isVerticalBarLayout()) { padding.top = 0; padding.bottom = edgeMarginPx; @@ -480,7 +425,7 @@ public class DeviceProfile { int availablePaddingX = Math.max(0, widthPx - ((inv.numColumns * cellWidthPx) + ((inv.numColumns - 1) * cellWidthPx))); availablePaddingX = (int) Math.min(availablePaddingX, - widthPx * MAX_HORIZONTAL_PADDING_PERCENT); + widthPx * MAX_HORIZONTAL_PADDING_PERCENT); int availablePaddingY = Math.max(0, heightPx - topWorkspacePadding - paddingBottom - (2 * inv.numRows * cellHeightPx) - hotseatBarTopPaddingPx - hotseatBarBottomPaddingPx); @@ -494,7 +439,6 @@ public class DeviceProfile { paddingBottom); } } - return padding; } /** @@ -517,18 +461,6 @@ public class DeviceProfile { } } - private int getWorkspacePageSpacing() { - if (isVerticalBarLayout() || isLargeTablet) { - // In landscape mode the page spacing is set to the default. - return defaultPageSpacingPx; - } else { - // In portrait, we want the pages spaced such that there is no - // overhang of the previous / next page into the current page viewport. - // We assume symmetrical padding in portrait mode. - return Math.max(defaultPageSpacingPx, getWorkspacePadding(null).left + 1); - } - } - public static int calculateCellWidth(int width, int countX) { return width / countX; } @@ -545,133 +477,10 @@ public class DeviceProfile { return isLandscape && transposeLayoutWithOrientation; } - boolean shouldFadeAdjacentWorkspaceScreens() { + public boolean shouldFadeAdjacentWorkspaceScreens() { return isVerticalBarLayout() || isLargeTablet; } - private static void setLayoutGravity(View v, int gravity) { - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) v.getLayoutParams(); - lp.gravity = gravity; - v.setLayoutParams(lp); - } - - public void layout(Launcher launcher, boolean notifyListeners) { - FrameLayout.LayoutParams lp; - boolean hasVerticalBarLayout = isVerticalBarLayout(); - - // Layout the search bar space - Point searchBarBounds = getSearchBarDimensForWidgetOpts(); - View searchBar = launcher.getDropTargetBar(); - lp = (FrameLayout.LayoutParams) searchBar.getLayoutParams(); - lp.width = searchBarBounds.x; - lp.height = searchBarBounds.y; - lp.topMargin = mInsets.top + edgeMarginPx; - searchBar.setLayoutParams(lp); - - // Layout the workspace - PagedView workspace = launcher.getWorkspace(); - Rect workspacePadding = getWorkspacePadding(null); - workspace.setPadding(workspacePadding.left, workspacePadding.top, workspacePadding.right, - workspacePadding.bottom); - workspace.setPageSpacing(getWorkspacePageSpacing()); - - AllAppsScrim allAppsScrim = launcher.findViewById(R.id.all_apps_scrim); - - // Layout the hotseat - Hotseat hotseat = launcher.getHotseat(); - lp = (FrameLayout.LayoutParams) hotseat.getLayoutParams(); - // 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 for - // this, we pad the left and right of the hotseat with half of the difference of a workspace - // cell vs a hotseat cell. - float workspaceCellWidth = (float) widthPx / inv.numColumns; - float hotseatCellWidth = (float) widthPx / inv.numHotseatIcons; - int hotseatAdjustment = Math.round((workspaceCellWidth - hotseatCellWidth) / 2); - float scrimMargin = launcher.getResources().getDimension(R.dimen.all_apps_scrim_margin); - - if (hasVerticalBarLayout) { - // Vertical hotseat, on left or right based on the insets - lp.height = LayoutParams.MATCH_PARENT; - if (mInsets.left > mInsets.right) { - lp.gravity = Gravity.LEFT; - lp.width = hotseatBarSizePx + mInsets.left + hotseatBarSidePaddingPx; - hotseat.getLayout().setPadding( - mInsets.left, mInsets.top, hotseatBarSidePaddingPx, mInsets.bottom); - - setLayoutGravity(launcher.getDropTargetBar(), Gravity.RIGHT); - } else { - lp.gravity = Gravity.RIGHT; - lp.width = hotseatBarSizePx + mInsets.right + hotseatBarSidePaddingPx; - hotseat.getLayout().setPadding( - hotseatBarSidePaddingPx, mInsets.top, mInsets.right, mInsets.bottom); - - setLayoutGravity(launcher.getDropTargetBar(), Gravity.LEFT); - } - - } else if (isTablet) { - // Pad the hotseat with the workspace padding calculated above - lp.gravity = Gravity.BOTTOM; - lp.width = LayoutParams.MATCH_PARENT; - lp.height = hotseatBarSizePx + mInsets.bottom; - allAppsScrim.setDrawRegion(lp.height + scrimMargin); - - hotseat.getLayout().setPadding(hotseatAdjustment + workspacePadding.left - + cellLayoutPaddingLeftRightPx, - hotseatBarTopPaddingPx, - hotseatAdjustment + workspacePadding.right + cellLayoutPaddingLeftRightPx, - hotseatBarBottomPaddingPx + mInsets.bottom + cellLayoutBottomPaddingPx); - } else { - // For phones, layout the hotseat without any bottom margin - // to ensure that we have space for the folders - lp.gravity = Gravity.BOTTOM; - lp.width = LayoutParams.MATCH_PARENT; - lp.height = hotseatBarSizePx + mInsets.bottom; - allAppsScrim.setDrawRegion(lp.height + scrimMargin); - - hotseat.getLayout().setPadding(hotseatAdjustment + workspacePadding.left - + cellLayoutPaddingLeftRightPx, - hotseatBarTopPaddingPx, - hotseatAdjustment + workspacePadding.right + cellLayoutPaddingLeftRightPx, - hotseatBarBottomPaddingPx + mInsets.bottom + cellLayoutBottomPaddingPx); - } - hotseat.setLayoutParams(lp); - - // Layout the page indicators - View pageIndicator = launcher.findViewById(R.id.page_indicator); - if (pageIndicator != null) { - lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams(); - if (hasVerticalBarLayout) { - if (mInsets.left > mInsets.right) { - lp.leftMargin = hotseatBarSidePaddingPx; - lp.rightMargin = mInsets.right; - lp.gravity = Gravity.RIGHT | Gravity.BOTTOM; - } else { - lp.leftMargin = mInsets.left; - lp.rightMargin = hotseatBarSidePaddingPx; - lp.gravity = Gravity.LEFT | Gravity.BOTTOM; - } - lp.bottomMargin = workspacePadding.bottom; - } else { - // Put the page indicators above the hotseat - lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; - lp.height = pageIndicatorSizePx; - lp.bottomMargin = hotseatBarSizePx + mInsets.bottom; - } - pageIndicator.setLayoutParams(lp); - } - - // Layout the AllAppsRecyclerView - AllAppsContainerView appsView = launcher.findViewById(R.id.apps_view); - int paddingLeftRight = desiredWorkspaceLeftRightMarginPx + cellLayoutPaddingLeftRightPx; - appsView.setRecyclerViewSidePadding(paddingLeftRight, paddingLeftRight); - - if (notifyListeners) { - for (int i = mListeners.size() - 1; i >= 0; i--) { - mListeners.get(i).onLauncherLayoutChanged(); - } - } - } - public int getCellHeight(@ContainerType int containerType) { switch (containerType) { case CellLayout.WORKSPACE: diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java index 106671f740..494aae45a8 100644 --- a/src/com/android/launcher3/DropTargetBar.java +++ b/src/com/android/launcher3/DropTargetBar.java @@ -21,15 +21,19 @@ import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessib import android.animation.TimeInterpolator; import android.content.Context; +import android.graphics.Rect; import android.util.AttributeSet; +import android.view.Gravity; import android.view.View; import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewPropertyAnimator; +import android.widget.FrameLayout; import android.widget.LinearLayout; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.dragndrop.DragController; +import com.android.launcher3.dragndrop.DragController.DragListener; import com.android.launcher3.dragndrop.DragOptions; import java.util.ArrayList; @@ -37,18 +41,14 @@ import java.util.ArrayList; /* * The top bar containing various drop targets: Delete/App Info/Uninstall. */ -public class DropTargetBar extends LinearLayout implements DragController.DragListener { +public class DropTargetBar extends LinearLayout + implements DragListener, Insettable { protected static final int DEFAULT_DRAG_FADE_DURATION = 175; protected static final TimeInterpolator DEFAULT_INTERPOLATOR = Interpolators.ACCEL; - private final Runnable mFadeAnimationEndRunnable = new Runnable() { - - @Override - public void run() { - updateVisibility(DropTargetBar.this, isAccessibilityEnabled(getContext())); - } - }; + private final Runnable mFadeAnimationEndRunnable = + () -> updateVisibility(DropTargetBar.this, isAccessibilityEnabled(getContext())); @ViewDebug.ExportedProperty(category = "launcher") protected boolean mDeferOnDragEnd; @@ -75,6 +75,40 @@ public class DropTargetBar extends LinearLayout implements DragController.DragLi setAlpha(0f); } + @Override + public void setInsets(Rect insets) { + FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); + DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile(); + + lp.leftMargin = insets.left; + lp.topMargin = insets.top; + lp.bottomMargin = insets.bottom; + lp.rightMargin = insets.right; + + if (grid.isVerticalBarLayout()) { + lp.width = grid.dropTargetBarSizePx; + lp.height = grid.availableHeightPx - 2 * grid.edgeMarginPx; + lp.gravity = insets.left > insets.right ? Gravity.RIGHT : Gravity.LEFT; + } 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 = grid.desiredWorkspaceLeftRightMarginPx - grid.defaultWidgetPadding.right; + } + lp.width = grid.availableWidthPx - 2 * gap; + + lp.topMargin += grid.edgeMarginPx; + lp.height = grid.dropTargetBarSizePx; + } + setLayoutParams(lp); + } + public void setup(DragController dragController) { dragController.addDragListener(this); ArrayList outList = new ArrayList<>(); diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java index 490fedaa2f..1f5aa138ce 100644 --- a/src/com/android/launcher3/Hotseat.java +++ b/src/com/android/launcher3/Hotseat.java @@ -22,27 +22,29 @@ import android.content.Context; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewDebug; +import android.view.ViewGroup; +import android.view.ViewGroup.LayoutParams; import android.widget.FrameLayout; import android.widget.TextView; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.logging.UserEventDispatcher; +import com.android.launcher3.logging.UserEventDispatcher.LogContainerProvider; import com.android.launcher3.userevent.nano.LauncherLogProto.Action; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType; import com.android.launcher3.userevent.nano.LauncherLogProto.Target; -public class Hotseat extends FrameLayout - implements UserEventDispatcher.LogContainerProvider { +public class Hotseat extends FrameLayout implements LogContainerProvider, Insettable { + private final Launcher mLauncher; private CellLayout mContent; - private Launcher mLauncher; - @ViewDebug.ExportedProperty(category = "launcher") private final boolean mHasVerticalHotseat; @@ -64,13 +66,6 @@ public class Hotseat extends FrameLayout return mContent; } - /** - * Returns whether there are other icons than the all apps button in the hotseat. - */ - public boolean hasIcons() { - return mContent.getShortcutsAndWidgets().getChildCount() > 1; - } - /** * Registers the specified listener on the cell layout of the hotseat. */ @@ -165,4 +160,46 @@ public class Hotseat extends FrameLayout target.gridY = info.cellY; targetParent.containerType = ContainerType.HOTSEAT; } + + @Override + public void setInsets(Rect insets) { + FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); + DeviceProfile grid = mLauncher.getDeviceProfile(); + if (mHasVerticalHotseat) { + lp.height = ViewGroup.LayoutParams.MATCH_PARENT; + if (insets.left > insets.right) { + lp.gravity = Gravity.LEFT; + lp.width = grid.hotseatBarSizePx + insets.left + grid.hotseatBarSidePaddingPx; + getLayout().setPadding( + insets.left, insets.top, grid.hotseatBarSidePaddingPx, insets.bottom); + + } else { + lp.gravity = Gravity.RIGHT; + lp.width = grid.hotseatBarSizePx + insets.right + grid.hotseatBarSidePaddingPx; + getLayout().setPadding( + grid.hotseatBarSidePaddingPx, insets.top, insets.right, insets.bottom); + } + } else { + lp.gravity = Gravity.BOTTOM; + lp.width = ViewGroup.LayoutParams.MATCH_PARENT; + lp.height = grid.hotseatBarSizePx + insets.bottom; + + // 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 for + // this, we pad the left and right of the hotseat with half of the difference of a workspace + // cell vs a hotseat cell. + float workspaceCellWidth = (float) grid.widthPx / grid.inv.numColumns; + float hotseatCellWidth = (float) grid.widthPx / grid.inv.numHotseatIcons; + int hotseatAdjustment = Math.round((workspaceCellWidth - hotseatCellWidth) / 2); + Rect workspacePadding = grid.workspacePadding; + + getLayout().setPadding( + hotseatAdjustment + workspacePadding.left + grid.cellLayoutPaddingLeftRightPx, + grid.hotseatBarTopPaddingPx, + hotseatAdjustment + workspacePadding.right + grid.cellLayoutPaddingLeftRightPx, + grid.hotseatBarBottomPaddingPx + insets.bottom + grid.cellLayoutBottomPaddingPx); + } + setLayoutParams(lp); + InsettableFrameLayout.dispatchInsets(this, insets); + } } diff --git a/src/com/android/launcher3/InsettableFrameLayout.java b/src/com/android/launcher3/InsettableFrameLayout.java index 60f5ca2925..baf3328eaf 100644 --- a/src/com/android/launcher3/InsettableFrameLayout.java +++ b/src/com/android/launcher3/InsettableFrameLayout.java @@ -97,4 +97,14 @@ public class InsettableFrameLayout extends FrameLayout implements Insettable { super.onViewAdded(child); setFrameLayoutChildInsets(child, mInsets, new Rect()); } + + public static void dispatchInsets(ViewGroup parent, Rect insets) { + final int n = parent.getChildCount(); + for (int i = 0; i < n; i++) { + final View child = parent.getChildAt(i); + if (child instanceof Insettable) { + ((Insettable) child).setInsets(insets); + } + } + } } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index adfb44cd7d..4d58593279 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -337,8 +337,6 @@ public class Launcher extends BaseActivity mLauncherView = LayoutInflater.from(this).inflate(R.layout.launcher, null); setupViews(); - mDeviceProfile.layout(this, false /* notifyListeners */); - mPopupDataProvider = new PopupDataProvider(this); mRotationEnabled = getResources().getBoolean(R.bool.allow_rotation); @@ -392,6 +390,7 @@ public class Launcher extends BaseActivity ? SCREEN_ORIENTATION_UNSPECIFIED : SCREEN_ORIENTATION_NOSENSOR); setContentView(mLauncherView); + ((LauncherRootView) mLauncherView).dispatchInsets(); // Listen for broadcasts IntentFilter filter = new IntentFilter(); @@ -441,11 +440,6 @@ public class Launcher extends BaseActivity private LauncherCallbacks mLauncherCallbacks; - public void onInsetsChanged(Rect insets) { - mDeviceProfile.updateInsets(insets); - mDeviceProfile.layout(this, true /* notifyListeners */); - } - /** * Call this after onCreate to set or clear overlay. */ diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java index a814323633..1a1bec6843 100644 --- a/src/com/android/launcher3/LauncherRootView.java +++ b/src/com/android/launcher3/LauncherRootView.java @@ -16,6 +16,8 @@ import static com.android.launcher3.util.SystemUiController.UI_STATE_ROOT_VIEW; public class LauncherRootView extends InsettableFrameLayout { + private final Launcher mLauncher; + private final Paint mOpaquePaint; @ViewDebug.ExportedProperty(category = "launcher") private boolean mDrawSideInsetBar; @@ -32,6 +34,8 @@ public class LauncherRootView extends InsettableFrameLayout { mOpaquePaint = new Paint(Paint.ANTI_ALIAS_FLAG); mOpaquePaint.setColor(Color.BLACK); mOpaquePaint.setStyle(Paint.Style.FILL); + + mLauncher = Launcher.getLauncher(context); } @Override @@ -57,10 +61,11 @@ public class LauncherRootView extends InsettableFrameLayout { } else { mLeftInsetBarWidth = mRightInsetBarWidth = 0; } - Launcher.getLauncher(getContext()).getSystemUiController().updateUiState( + mLauncher.getSystemUiController().updateUiState( UI_STATE_ROOT_VIEW, mDrawSideInsetBar ? FLAG_DARK_NAV : 0); - boolean rawInsetsChanged = !mInsets.equals(insets); + // Update device profile before notifying th children. + mLauncher.getDeviceProfile().updateInsets(insets); setInsets(insets); if (mAlignedView != null) { @@ -73,15 +78,13 @@ public class LauncherRootView extends InsettableFrameLayout { } } - if (rawInsetsChanged) { - // Update the grid again - Launcher launcher = Launcher.getLauncher(getContext()); - launcher.onInsetsChanged(insets); - } - return true; // I'll take it from here } + public void dispatchInsets() { + fitSystemWindows(mInsets); + } + @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 1b72f8338a..893d8202b2 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -310,6 +310,20 @@ public class Workspace extends PagedView @Override public void setInsets(Rect insets) { mInsets.set(insets); + + DeviceProfile grid = mLauncher.getDeviceProfile(); + Rect padding = grid.workspacePadding; + setPadding(padding.left, padding.top, padding.right, padding.bottom); + + if (grid.shouldFadeAdjacentWorkspaceScreens()) { + // In landscape mode the page spacing is set to the default. + setPageSpacing(grid.defaultPageSpacingPx); + } else { + // In portrait, we want the pages spaced such that there is no + // overhang of the previous / next page into the current page viewport. + // We assume symmetrical padding in portrait mode. + setPageSpacing(Math.max(grid.defaultPageSpacingPx, padding.left + 1)); + } } /** diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 2a7f46a58f..5e188e9501 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -44,6 +44,7 @@ import com.android.launcher3.DragSource; import com.android.launcher3.DropTarget; import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.Insettable; +import com.android.launcher3.InsettableFrameLayout; import com.android.launcher3.ItemInfo; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; @@ -69,8 +70,7 @@ import java.util.Set; * The all apps view container. */ public class AllAppsContainerView extends RelativeLayout implements DragSource, - View.OnLongClickListener, Insettable, DeviceProfile.LauncherLayoutChangeListener, - BubbleTextView.BubbleTextShadowHandler { + View.OnLongClickListener, Insettable, BubbleTextView.BubbleTextShadowHandler { private final Launcher mLauncher; private final AdapterHolder[] mAH; @@ -126,11 +126,6 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource, @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - - DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile(); - grid.addLauncherLayoutChangedListener(this); - onLauncherLayoutChanged(); - applyTouchDelegate(); } @@ -138,28 +133,6 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource, // TODO: Reimplement once fast scroller is fixed. } - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - - DeviceProfile grid = Launcher.getLauncher(getContext()).getDeviceProfile(); - grid.removeLauncherLayoutChangedListener(this); - } - - /** - * Calculate the background padding as it can change due to insets/content padding change. - */ - @Override - public void onLauncherLayoutChanged() { - DeviceProfile grid = mLauncher.getDeviceProfile(); - if (!grid.isVerticalBarLayout()) { - return; - } - - Rect workspacePadding = grid.getWorkspacePadding(null); - setPadding(workspacePadding.left, 0, workspacePadding.right, 0); - } - @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); @@ -364,8 +337,12 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource, @Override public void setInsets(Rect insets) { DeviceProfile grid = mLauncher.getDeviceProfile(); + int leftRightPadding = grid.desiredWorkspaceLeftRightMarginPx + + grid.cellLayoutPaddingLeftRightPx; + for (int i = 0; i < mAH.length; i++) { mAH[i].padding.bottom = insets.bottom; + mAH[i].padding.left = mAH[i].padding.right = leftRightPadding; mAH[i].applyPadding(); } if (grid.isVerticalBarLayout()) { @@ -374,12 +351,14 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource, mlp.topMargin = insets.top; mlp.rightMargin = insets.right; setLayoutParams(mlp); + setPadding(grid.workspacePadding.left, 0, grid.workspacePadding.right, 0); } else { View navBarBg = findViewById(R.id.nav_bar_bg); ViewGroup.LayoutParams navBarBgLp = navBarBg.getLayoutParams(); navBarBgLp.height = insets.bottom; navBarBg.setLayoutParams(navBarBgLp); } + InsettableFrameLayout.dispatchInsets(this, insets); } public void updateIconBadges(Set updatedBadges) { @@ -575,14 +554,6 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource, } } - public void setRecyclerViewSidePadding(int left, int right) { - for (int i = 0; i < mAH.length; i++) { - mAH[i].padding.left = left; - mAH[i].padding.right = right; - mAH[i].applyPadding(); - } - } - public void setRecyclerViewVerticalFadingEdgeEnabled(boolean enabled) { for (int i = 0; i < mAH.length; i++) { mAH[i].applyVerticalFadingEdgeEnabled(enabled); diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorLandscape.java b/src/com/android/launcher3/pageindicators/PageIndicatorLandscape.java index 2d5a4a9385..d76998a43a 100644 --- a/src/com/android/launcher3/pageindicators/PageIndicatorLandscape.java +++ b/src/com/android/launcher3/pageindicators/PageIndicatorLandscape.java @@ -18,10 +18,16 @@ package com.android.launcher3.pageindicators; import static com.android.launcher3.LauncherState.ALL_APPS; import android.content.Context; +import android.graphics.Rect; import android.util.AttributeSet; +import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; +import android.view.ViewGroup.MarginLayoutParams; +import android.widget.FrameLayout; +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Insettable; import com.android.launcher3.Launcher; import com.android.launcher3.userevent.nano.LauncherLogProto.Action; import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType; @@ -31,9 +37,11 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType; * a view with as large an area as we want (for touching) while maintaining a caret of size * all_apps_caret_size. Used only for the landscape layout. */ -public class PageIndicatorLandscape extends PageIndicator implements OnClickListener { +public class PageIndicatorLandscape extends PageIndicator implements OnClickListener, Insettable { // all apps pull up handle drawable. + private final Launcher mLauncher; + public PageIndicatorLandscape(Context context) { this(context, null); } @@ -45,7 +53,8 @@ public class PageIndicatorLandscape extends PageIndicator implements OnClickList public PageIndicatorLandscape(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setOnClickListener(this); - setOnFocusChangeListener(Launcher.getLauncher(context).mFocusHandler); + mLauncher = Launcher.getLauncher(context); + setOnFocusChangeListener(mLauncher.mFocusHandler); } @Override @@ -57,4 +66,21 @@ public class PageIndicatorLandscape extends PageIndicator implements OnClickList l.getStateManager().goToState(ALL_APPS); } } + + @Override + public void setInsets(Rect insets) { + FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); + DeviceProfile grid = mLauncher.getDeviceProfile(); + if (insets.left > insets.right) { + lp.leftMargin = grid.hotseatBarSidePaddingPx; + lp.rightMargin = insets.right; + lp.gravity = Gravity.RIGHT | Gravity.BOTTOM; + } else { + lp.leftMargin = insets.left; + lp.rightMargin = grid.hotseatBarSidePaddingPx; + lp.gravity = Gravity.LEFT | Gravity.BOTTOM; + } + lp.bottomMargin = grid.workspacePadding.bottom; + setLayoutParams(lp); + } } diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorLine.java b/src/com/android/launcher3/pageindicators/PageIndicatorLine.java index 6c4b89820f..8c9642ccdd 100644 --- a/src/com/android/launcher3/pageindicators/PageIndicatorLine.java +++ b/src/com/android/launcher3/pageindicators/PageIndicatorLine.java @@ -9,12 +9,17 @@ import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.Rect; import android.os.Handler; import android.os.Looper; import android.util.AttributeSet; import android.util.Property; +import android.view.Gravity; import android.view.ViewConfiguration; +import android.widget.FrameLayout; +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.Insettable; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Utilities; @@ -25,7 +30,7 @@ import com.android.launcher3.dynamicui.WallpaperColorInfo; * * The fraction is 1 / number of pages and the position is based on the progress of the page scroll. */ -public class PageIndicatorLine extends PageIndicator { +public class PageIndicatorLine extends PageIndicator implements Insettable { private static final int LINE_ANIMATE_DURATION = ViewConfiguration.getScrollBarFadeDuration(); private static final int LINE_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay(); @@ -39,6 +44,7 @@ public class PageIndicatorLine extends PageIndicator { private ValueAnimator[] mAnimators = new ValueAnimator[3]; private final Handler mDelayedLineFadeHandler = new Handler(Looper.getMainLooper()); + private final Launcher mLauncher; private boolean mShouldAutoHide = true; @@ -51,7 +57,6 @@ public class PageIndicatorLine extends PageIndicator { private int mCurrentScroll; private int mTotalScroll; private Paint mLinePaint; - private Launcher mLauncher; private final int mLineHeight; private static final Property PAINT_ALPHA @@ -224,4 +229,14 @@ public class PageIndicatorLine extends PageIndicator { mAnimators[animatorIndex].setDuration(LINE_ANIMATE_DURATION); mAnimators[animatorIndex].start(); } + + @Override + public void setInsets(Rect insets) { + DeviceProfile grid = mLauncher.getDeviceProfile(); + FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams(); + lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; + lp.height = grid.pageIndicatorSizePx; + lp.bottomMargin = grid.hotseatBarSizePx + insets.bottom; + setLayoutParams(lp); + } } diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java index ddcd8ae673..6d584cd1b5 100644 --- a/src/com/android/launcher3/states/SpringLoadedState.java +++ b/src/com/android/launcher3/states/SpringLoadedState.java @@ -65,7 +65,7 @@ public class SpringLoadedState extends LauncherState { float scaledHeight = scale * ws.getNormalChildHeight(); float shrunkTop = insets.top + grid.dropTargetBarSizePx; float shrunkBottom = ws.getMeasuredHeight() - insets.bottom - - grid.getWorkspacePadding(null).bottom + - grid.workspacePadding.bottom - grid.workspaceSpringLoadedBottomSpace; float totalShrunkSpace = shrunkBottom - shrunkTop; diff --git a/src/com/android/launcher3/views/AllAppsScrim.java b/src/com/android/launcher3/views/AllAppsScrim.java index 17ddae313f..5d39adb4e4 100644 --- a/src/com/android/launcher3/views/AllAppsScrim.java +++ b/src/com/android/launcher3/views/AllAppsScrim.java @@ -30,14 +30,14 @@ import com.android.launcher3.Insettable; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.dynamicui.WallpaperColorInfo; +import com.android.launcher3.dynamicui.WallpaperColorInfo.OnChangeListener; import com.android.launcher3.graphics.NinePatchDrawHelper; import com.android.launcher3.graphics.ShadowGenerator; import com.android.launcher3.util.Themes; import static com.android.launcher3.graphics.NinePatchDrawHelper.EXTENSION_PX; -public class AllAppsScrim extends View implements WallpaperColorInfo.OnChangeListener, Insettable, - DeviceProfile.LauncherLayoutChangeListener { +public class AllAppsScrim extends View implements OnChangeListener, Insettable { private static final int MAX_ALPHA = 235; private static final int MIN_ALPHA_PORTRAIT = 100; @@ -112,15 +112,12 @@ public class AllAppsScrim extends View implements WallpaperColorInfo.OnChangeLis protected void onAttachedToWindow() { super.onAttachedToWindow(); mWallpaperColorInfo.addOnChangeListener(this); - mGrid.addLauncherLayoutChangedListener(this); - onLauncherLayoutChanged(); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); mWallpaperColorInfo.removeOnChangeListener(this); - mGrid.removeLauncherLayoutChangedListener(this); } @Override @@ -171,19 +168,16 @@ public class AllAppsScrim extends View implements WallpaperColorInfo.OnChangeLis @Override public void setInsets(Rect insets) { mInsets.set(insets); - onLauncherLayoutChanged(); - } - - @Override - public void onLauncherLayoutChanged() { - if (!mGrid.isVerticalBarLayout()) { - return; + if (mGrid.isVerticalBarLayout()) { + mPadding.set(mGrid.workspacePadding); + mPadding.bottom = 0; + mPadding.left += mInsets.left; + mPadding.top = mInsets.top; + mPadding.right += mInsets.right; + } else { + float scrimMargin = getResources().getDimension(R.dimen.all_apps_scrim_margin); + setDrawRegion(mGrid.hotseatBarSizePx + insets.bottom + scrimMargin); } - mGrid.getWorkspacePadding(mPadding); - mPadding.bottom = 0; - mPadding.left += mInsets.left; - mPadding.top = mInsets.top; - mPadding.right += mInsets.right; invalidate(); } } diff --git a/src/com/android/launcher3/widget/WidgetsFullSheet.java b/src/com/android/launcher3/widget/WidgetsFullSheet.java index a40ea1b644..a1bfe88498 100644 --- a/src/com/android/launcher3/widget/WidgetsFullSheet.java +++ b/src/com/android/launcher3/widget/WidgetsFullSheet.java @@ -42,8 +42,6 @@ public class WidgetsFullSheet extends BaseWidgetSheet private static final long FADE_IN_DURATION = 150; private static final float VERTICAL_START_POSITION = 0.3f; - private static final Rect sTempRect = new Rect(); - private final Rect mInsets = new Rect(); private final WidgetsListAdapter mAdapter; @@ -115,8 +113,8 @@ public class WidgetsFullSheet extends BaseWidgetSheet mGradientView.setVisibility(View.INVISIBLE); widthUsed = 0; } else { - mLauncher.getDeviceProfile().getWorkspacePadding(sTempRect); - widthUsed = Math.max(sTempRect.left + sTempRect.right, + Rect padding = mLauncher.getDeviceProfile().workspacePadding; + widthUsed = Math.max(padding.left + padding.right, 2 * (mInsets.left + mInsets.right)); } diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/OverviewState.java b/src_ui_overrides/com/android/launcher3/uioverrides/OverviewState.java index 346882736f..d18901d361 100644 --- a/src_ui_overrides/com/android/launcher3/uioverrides/OverviewState.java +++ b/src_ui_overrides/com/android/launcher3/uioverrides/OverviewState.java @@ -51,9 +51,8 @@ public class OverviewState extends LauncherState { int overviewButtonBarHeight = OverviewPanel.getButtonBarHeight(launcher); int scaledHeight = (int) (SCALE_FACTOR * ws.getNormalChildHeight()); - Rect workspacePadding = grid.getWorkspacePadding(null); - int workspaceTop = insets.top + workspacePadding.top; - int workspaceBottom = ws.getHeight() - insets.bottom - workspacePadding.bottom; + int workspaceTop = insets.top + grid.workspacePadding.top; + int workspaceBottom = ws.getHeight() - insets.bottom - grid.workspacePadding.bottom; int overviewTop = insets.top; int overviewBottom = ws.getHeight() - insets.bottom - overviewButtonBarHeight; int workspaceOffsetTopEdge =