Allow user to tap on stashed app to launch task in fullscreen
This patch implements a new feature that allows the user to tap on the staged app rectangle in split staging mode. When the user does so, split selection will be canceled, and the staged app will animate out to fill the screen and launch in fullscreen.
Done by creating a new onClick listener on mFirstFloatingTaskView that sets up the screen-filling animation, and then calls a new RecentsView function, launchStagedTask(), that launches mSplitHiddenTaskView and cleans up RecentsView afterwards (similar to what happens when a split pair is selected, but only one app is launched).
Open issues:
- After the staged task animates out to fill the screen, the task itself loads instantly without animating in. Ideally, it should fade in, similar to what happens when two split tasks are loaded in.
Bug: 257513449
Test: Manual on tablet
Change-Id: I2ae8e13e1c9848aae1978a536766c370949fd08b
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
index 2966fbb..7dc1b32 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
@@ -25,7 +25,7 @@
*/
public interface SplitAnimationTimings {
int TABLET_ENTER_DURATION = 866;
- int TABLET_CONFIRM_DURATION = 383;
+ int TABLET_CONFIRM_DURATION = 500;
int PHONE_ENTER_DURATION = 517;
int PHONE_CONFIRM_DURATION = 333;
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index ff0c984..2474b69 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -41,6 +41,7 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_0_75;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_LAUNCH_FROM_STAGED_APP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ACTIONS_SPLIT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
@@ -125,7 +126,6 @@
import androidx.annotation.UiThread;
import androidx.core.graphics.ColorUtils;
-import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.BaseActivity.MultiWindowModeChangedListener;
import com.android.launcher3.DeviceProfile;
@@ -2903,6 +2903,11 @@
false /* fadeWithThumbnail */, true /* isStagedTask */);
}
+ // TODO (b/257513449): Launch animation not fully complete. OK to remove flag once it is.
+ if (ENABLE_LAUNCH_FROM_STAGED_APP.get()) {
+ mFirstFloatingTaskView.setOnClickListener(this::animateToFullscreen);
+ }
+
// SplitInstructionsView: animate in
safeRemoveDragLayerView(mSplitInstructionsView);
mSplitInstructionsView = SplitInstructionsView.getSplitInstructionsView(mActivity);
@@ -2946,6 +2951,34 @@
});
}
+ private void animateToFullscreen(View view) {
+ FloatingTaskView stagedTaskView = (FloatingTaskView) view;
+
+ boolean isTablet = mActivity.getDeviceProfile().isTablet;
+ int duration = isTablet
+ ? SplitAnimationTimings.TABLET_CONFIRM_DURATION
+ : SplitAnimationTimings.PHONE_CONFIRM_DURATION;
+
+ PendingAnimation pendingAnimation = new PendingAnimation(duration);
+
+ Rect firstTaskStartingBounds = new Rect();
+ Rect firstTaskEndingBounds = new Rect();
+
+ stagedTaskView.getBoundsOnScreen(firstTaskStartingBounds);
+ mActivity.getDragLayer().getBoundsOnScreen(firstTaskEndingBounds);
+
+ stagedTaskView.addConfirmAnimation(
+ pendingAnimation,
+ new RectF(firstTaskStartingBounds),
+ firstTaskEndingBounds,
+ false /* fadeWithThumbnail */,
+ true /* isStagedTask */);
+
+ pendingAnimation.addEndListener(success -> launchStagedTask());
+
+ pendingAnimation.buildAnim().start();
+ }
+
/**
* Creates a {@link PendingAnimation} for dismissing the specified {@link TaskView}.
* @param dismissedTaskView the {@link TaskView} to be dismissed
@@ -4294,11 +4327,8 @@
Rect firstTaskEndingBounds = mTempRect;
boolean isTablet = mActivity.getDeviceProfile().isTablet;
- int duration = isTablet
- ? SplitAnimationTimings.TABLET_CONFIRM_DURATION
- : SplitAnimationTimings.PHONE_CONFIRM_DURATION;
- PendingAnimation pendingAnimation = new PendingAnimation(duration);
SplitAnimationTimings timings = AnimUtils.getDeviceSplitToConfirmTimings(isTablet);
+ PendingAnimation pendingAnimation = new PendingAnimation(timings.getDuration());
int halfDividerSize = getResources()
.getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
@@ -4650,6 +4680,16 @@
return mPendingAnimation;
}
+ protected void launchStagedTask() {
+ if (mSplitHiddenTaskView != null) {
+ // Split staging was started from an existing running task (in Overview)
+ mSplitHiddenTaskView.launchTask(success -> resetFromSplitSelectionState());
+ } else {
+ // Split staging was started from a new intent (from app menu in Home/AllApps)
+ mActivity.startActivity(mSplitSelectSource.intent);
+ }
+ }
+
protected void onTaskLaunchAnimationEnd(boolean success) {
if (success) {
resetTaskVisuals();
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 33f3bfd..e20489c 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -342,6 +342,11 @@
public static final BooleanFlag ENABLE_DEVICE_PROFILE_LOGGING = new DeviceFlag(
"ENABLE_DEVICE_PROFILE_LOGGING", false, "Allows DeviceProfile logging");
+ public static final BooleanFlag ENABLE_LAUNCH_FROM_STAGED_APP = getDebugFlag(
+ "ENABLE_LAUNCH_FROM_STAGED_APP", false,
+ "Enable the ability to tap a staged app during split select to launch it in full screen"
+ );
+
public static void initialize(Context context) {
synchronized (sDebugFlags) {
for (DebugFlag flag : sDebugFlags) {