Overview actions - adds feature flag and base class for Overview Actions.
Adds ENABLE_OVERVIEW_ACTIONS feature flag and base factory. Requires an
implementation in overlay to show any actions.
Test: run locally with flag on and off.
Bug: 145628186
Change-Id: I1c36330464cc01e1e987ebfea1a9f451067598a5
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
index ed5dba1..bd37e56 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -44,6 +44,7 @@
import com.android.launcher3.Workspace;
import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.SysUINavigationMode;
@@ -140,6 +141,10 @@
if (launcher.getDeviceProfile().isVerticalBarLayout()) {
return VERTICAL_SWIPE_INDICATOR | RECENTS_CLEAR_ALL_BUTTON;
} else {
+ if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) {
+ return VERTICAL_SWIPE_INDICATOR | RECENTS_CLEAR_ALL_BUTTON;
+ }
+
boolean hasAllAppsHeaderExtra = launcher.getAppsView() != null
&& launcher.getAppsView().getFloatingHeaderView().hasVisibleContent();
return HOTSEAT_SEARCH_BOX | VERTICAL_SWIPE_INDICATOR | RECENTS_CLEAR_ALL_BUTTON |
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewActionsFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewActionsFactory.java
new file mode 100644
index 0000000..6d17b27
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewActionsFactory.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.quickstep;
+
+import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
+
+import android.view.View;
+
+import com.android.launcher3.R;
+import com.android.launcher3.util.MainThreadInitializedObject;
+import com.android.launcher3.util.ResourceBasedOverride;
+
+/**
+ * Overview actions are shown in overview underneath the task snapshot. This factory class is
+ * overrideable in an overlay. The {@link OverviewActions} class provides the view that should be
+ * shown in the Overview.
+ */
+public class OverviewActionsFactory implements ResourceBasedOverride {
+
+ public static final MainThreadInitializedObject<OverviewActionsFactory> INSTANCE =
+ forOverride(OverviewActionsFactory.class, R.string.overview_actions_factory_class);
+
+ /** Create a new Overview Actions for interacting between the actions and overview. */
+ public OverviewActions createOverviewActions() {
+ return new OverviewActions();
+ }
+
+ /** Overlay overrideable, base class does nothing. */
+ public static class OverviewActions {
+ /** Get the view to show in the overview. */
+ public View getView() {
+ return null;
+ }
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index b602cea..a8d88b9 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -111,6 +111,7 @@
import com.android.quickstep.TaskUtils;
import com.android.quickstep.ViewUtils;
import com.android.quickstep.util.AppWindowAnimationHelper;
+import com.android.quickstep.util.LayoutUtils;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -344,8 +345,7 @@
setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
mTaskTopMargin = getResources()
.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
- mTaskBottomMargin = getResources().getDimensionPixelSize(
- R.dimen.task_thumbnail_bottom_margin);
+ mTaskBottomMargin = LayoutUtils.thumbnailBottomMargin(getResources());
mSquaredTouchSlop = squaredTouchSlop(context);
mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents);
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index 0bfde64..94cec72 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -47,11 +47,14 @@
import android.widget.FrameLayout;
import android.widget.Toast;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.popup.SystemShortcut;
import com.android.launcher3.userevent.nano.LauncherLogProto;
@@ -59,11 +62,13 @@
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.util.ViewPool.Reusable;
+import com.android.quickstep.OverviewActionsFactory;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskIconCache;
import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
+import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.TaskCornerRadius;
import com.android.quickstep.views.RecentsView.PageCallbacks;
import com.android.quickstep.views.RecentsView.ScrollState;
@@ -159,6 +164,9 @@
private final float mWindowCornerRadius;
private final BaseDraggingActivity mActivity;
+ private OverviewActionsFactory.OverviewActions mOverviewActions;
+ @Nullable private View mActionsView;
+
private ObjectAnimator mIconAndDimAnimator;
private float mIconScaleAnimStartProgress = 0;
private float mFocusTransitionProgress = 1;
@@ -214,6 +222,7 @@
mCurrentFullscreenParams = new FullscreenDrawParams(mCornerRadius);
mDigitalWellBeingToast = new DigitalWellBeingToast(mActivity, this);
+ mOverviewActions = OverviewActionsFactory.INSTANCE.get(context).createOverviewActions();
mOutlineProvider = new TaskOutlineProvider(getResources(), mCurrentFullscreenParams);
setOutlineProvider(mOutlineProvider);
}
@@ -223,6 +232,21 @@
super.onFinishInflate();
mSnapshotView = findViewById(R.id.snapshot);
mIconView = findViewById(R.id.icon);
+
+ TaskView.LayoutParams thumbnailParams = (LayoutParams) mSnapshotView.getLayoutParams();
+ thumbnailParams.bottomMargin = LayoutUtils.thumbnailBottomMargin(getResources());
+ mSnapshotView.setLayoutParams(thumbnailParams);
+
+
+ if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) {
+ mActionsView = mOverviewActions.getView();
+ if (mActionsView != null) {
+ TaskView.LayoutParams params = new TaskView.LayoutParams(LayoutParams.MATCH_PARENT,
+ getResources().getDimensionPixelSize(R.dimen.overview_actions_height),
+ Gravity.BOTTOM);
+ addView(mActionsView, params);
+ }
+ }
}
public TaskMenuView getMenuView() {
@@ -422,6 +446,10 @@
mIconView.setScaleX(scale);
mIconView.setScaleY(scale);
+ if (mActionsView != null) {
+ mActionsView.setAlpha(scale);
+ }
+
mFooterVerticalOffset = 1.0f - scale;
for (FooterWrapper footer : mFooters) {
if (footer != null) {
@@ -626,7 +654,7 @@
TaskOutlineProvider(Resources res, FullscreenDrawParams fullscreenParams) {
mMarginTop = res.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
- mMarginBottom = res.getDimensionPixelSize(R.dimen.task_thumbnail_bottom_margin);
+ mMarginBottom = LayoutUtils.thumbnailBottomMargin(res);
mFullscreenParams = fullscreenParams;
}
@@ -783,6 +811,7 @@
/**
* Hides the icon and shows insets when this TaskView is about to be shown fullscreen.
+ *
* @param progress: 0 = show icon and no insets; 1 = don't show icon and show full insets.
*/
public void setFullscreenProgress(float progress) {
@@ -793,6 +822,9 @@
mFullscreenProgress = progress;
boolean isFullscreen = mFullscreenProgress > 0;
mIconView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
+ if (mActionsView != null) {
+ mActionsView.setVisibility(progress < 1 ? VISIBLE : INVISIBLE);
+ }
setClipChildren(!isFullscreen);
setClipToPadding(!isFullscreen);
@@ -873,4 +905,5 @@
mScale = scale;
}
}
+
}
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index 7a36416..60cfa0c 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -25,8 +25,7 @@
android:id="@+id/snapshot"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_marginTop="@dimen/task_thumbnail_top_margin"
- android:layout_marginBottom="@dimen/task_thumbnail_bottom_margin"/>
+ android:layout_marginTop="@dimen/task_thumbnail_top_margin"/>
<com.android.quickstep.views.IconView
android:id="@+id/icon"
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index 327bb14..24ab487 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -15,6 +15,8 @@
-->
<resources>
<string name="task_overlay_factory_class" translatable="false"></string>
+ <!-- Class name for factory object that creates the overview actions UI when enabled. -->
+ <string name="overview_actions_factory_class" translatable="false" />
<!-- Activity which blocks home gesture -->
<string name="gesture_blocking_activity" translatable="false"></string>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 82833ea..9ff1350 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -18,12 +18,13 @@
<dimen name="task_thumbnail_top_margin">24dp</dimen>
<dimen name="task_thumbnail_half_top_margin">12dp</dimen>
- <!-- Can be overridden in overlays. -->
- <dimen name="task_thumbnail_bottom_margin">0dp</dimen>
<dimen name="task_thumbnail_icon_size">48dp</dimen>
<!-- For screens without rounded corners -->
<dimen name="task_corner_radius_small">2dp</dimen>
+ <!-- Overrideable in overlay that provides the Overview Actions. -->
+ <dimen name="overview_actions_height">0dp</dimen>
+
<dimen name="recents_page_spacing">10dp</dimen>
<dimen name="recents_clear_all_deadzone_vertical_margin">70dp</dimen>
<dimen name="overview_peek_distance">96dp</dimen>
@@ -58,6 +59,7 @@
<dimen name="task_card_menu_shadow_height">3dp</dimen>
<dimen name="task_card_menu_horizontal_padding">0dp</dimen>
<dimen name="portrait_task_card_horz_space">136dp</dimen>
+ <dimen name="portrait_task_card_horz_space_big_overview">24dp</dimen>
<dimen name="landscape_task_card_horz_space">200dp</dimen>
<dimen name="multi_window_task_card_horz_space">100dp</dimen>
<!-- Copied from framework resource:
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index c47bb4a..d49ff89 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -26,6 +26,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
+import com.android.launcher3.config.FeatureFlags;
import com.android.quickstep.SysUINavigationMode;
import java.lang.annotation.Retention;
@@ -57,9 +58,16 @@
} else {
Resources res = context.getResources();
- extraSpace = getDefaultSwipeHeight(context, dp) + dp.verticalDragHandleSizePx
- + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size)
- + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
+ if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) {
+ //TODO: this needs to account for the swipe gesture height and accessibility
+ // UI when shown.
+ extraSpace = 0;
+ } else {
+ extraSpace = getDefaultSwipeHeight(context, dp) + dp.verticalDragHandleSizePx
+ + res.getDimensionPixelSize(
+ R.dimen.dynamic_grid_hotseat_extra_vertical_size)
+ + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
+ }
}
calculateTaskSize(context, dp, extraSpace, MULTI_WINDOW_STRATEGY_HALF_SCREEN, outRect);
}
@@ -99,13 +107,20 @@
} else {
taskWidth = dp.availableWidthPx;
taskHeight = dp.availableHeightPx;
- paddingHorz = res.getDimension(dp.isVerticalBarLayout()
- ? R.dimen.landscape_task_card_horz_space
- : R.dimen.portrait_task_card_horz_space);
+
+ final int paddingResId;
+ if (dp.isVerticalBarLayout()) {
+ paddingResId = R.dimen.landscape_task_card_horz_space;
+ } else if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) {
+ paddingResId = R.dimen.portrait_task_card_horz_space_big_overview;
+ } else {
+ paddingResId = R.dimen.portrait_task_card_horz_space;
+ }
+ paddingHorz = res.getDimension(paddingResId);
}
- float topIconMargin = res.getDimension(R.dimen.task_thumbnail_top_margin);
- float bottomMargin = res.getDimension(R.dimen.task_thumbnail_bottom_margin);
+ float topIconMargin = res.getDimension(R.dimen.task_thumbnail_top_margin);
+ float bottomMargin = thumbnailBottomMargin(res);
float paddingVert = res.getDimension(R.dimen.task_card_vert_space);
// Note this should be same as dp.availableWidthPx and dp.availableHeightPx unless
@@ -136,4 +151,16 @@
R.dimen.task_card_vert_space);
return shelfHeight + spaceBetweenShelfAndRecents;
}
+
+ /**
+ * Get the margin that the task thumbnail view should use.
+ * @return the margin in pixels.
+ */
+ public static int thumbnailBottomMargin(Resources resources) {
+ if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()) {
+ return resources.getDimensionPixelSize(R.dimen.overview_actions_height);
+ } else {
+ return 0;
+ }
+ }
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 1ae30b7..80c7056 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -130,6 +130,9 @@
"ENABLE_LAUNCHER_PREVIEW_IN_GRID_PICKER", false,
"Show launcher preview in grid picker");
+ public static final TogglableFlag ENABLE_OVERVIEW_ACTIONS = new TogglableFlag(
+ "ENABLE_OVERVIEW_ACTIONS", false, "Show app actions in Overview");
+
public static void initialize(Context context) {
// Avoid the disk read for user builds
if (Utilities.IS_DEBUG_DEVICE) {