Launch GroupedTaskView from thumbnails
* Previously when starting the remote animation we were relying on SplitPlaceholderViews to animate into the proper place since we weren't launching from the TaskView itself * Now when launching from a GroupedTaskView, we use the existing animation that handles that animation in addition to showing the new split tasks Fixes: 206608786 Test: Thumbnails animate from home -> overview -> launch Change-Id: I1499ead7d90cd41e285ed0f4df66ea31f0dfbc95
This commit is contained in:
@@ -301,7 +301,8 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
|||||||
mActionsView = findViewById(R.id.overview_actions_view);
|
mActionsView = findViewById(R.id.overview_actions_view);
|
||||||
RecentsView overviewPanel = (RecentsView) getOverviewPanel();
|
RecentsView overviewPanel = (RecentsView) getOverviewPanel();
|
||||||
SplitSelectStateController controller =
|
SplitSelectStateController controller =
|
||||||
new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this));
|
new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this),
|
||||||
|
getStateManager(), getDepthController());
|
||||||
overviewPanel.init(mActionsView, controller);
|
overviewPanel.init(mActionsView, controller);
|
||||||
mActionsView.setDp(getDeviceProfile());
|
mActionsView.setDp(getDeviceProfile());
|
||||||
mActionsView.updateVerticalMargin(SysUINavigationMode.getMode(this));
|
mActionsView.updateVerticalMargin(SysUINavigationMode.getMode(this));
|
||||||
|
|||||||
@@ -128,7 +128,8 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
|||||||
SYSUI_PROGRESS.set(getRootView().getSysUiScrim(), 0f);
|
SYSUI_PROGRESS.set(getRootView().getSysUiScrim(), 0f);
|
||||||
|
|
||||||
SplitSelectStateController controller =
|
SplitSelectStateController controller =
|
||||||
new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this));
|
new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this),
|
||||||
|
getStateManager(), null /*depthController*/);
|
||||||
mDragLayer.recreateControllers();
|
mDragLayer.recreateControllers();
|
||||||
mFallbackRecentsView.init(mActionsView, controller);
|
mFallbackRecentsView.init(mActionsView, controller);
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ import android.view.View;
|
|||||||
import android.window.TransitionInfo;
|
import android.window.TransitionInfo;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.launcher3.BaseActivity;
|
import com.android.launcher3.BaseActivity;
|
||||||
import com.android.launcher3.DeviceProfile;
|
import com.android.launcher3.DeviceProfile;
|
||||||
@@ -72,6 +73,7 @@ import com.android.quickstep.util.MultiValueUpdateListener;
|
|||||||
import com.android.quickstep.util.SurfaceTransactionApplier;
|
import com.android.quickstep.util.SurfaceTransactionApplier;
|
||||||
import com.android.quickstep.util.TaskViewSimulator;
|
import com.android.quickstep.util.TaskViewSimulator;
|
||||||
import com.android.quickstep.util.TransformParams;
|
import com.android.quickstep.util.TransformParams;
|
||||||
|
import com.android.quickstep.views.GroupedTaskView;
|
||||||
import com.android.quickstep.views.RecentsView;
|
import com.android.quickstep.views.RecentsView;
|
||||||
import com.android.quickstep.views.TaskThumbnailView;
|
import com.android.quickstep.views.TaskThumbnailView;
|
||||||
import com.android.quickstep.views.TaskView;
|
import com.android.quickstep.views.TaskView;
|
||||||
@@ -149,10 +151,12 @@ public final class TaskViewUtils {
|
|||||||
return taskView;
|
return taskView;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void createRecentsWindowAnimator(TaskView v, boolean skipViewChanges,
|
public static void createRecentsWindowAnimator(
|
||||||
RemoteAnimationTargetCompat[] appTargets,
|
@NonNull TaskView v, boolean skipViewChanges,
|
||||||
RemoteAnimationTargetCompat[] wallpaperTargets,
|
@NonNull RemoteAnimationTargetCompat[] appTargets,
|
||||||
RemoteAnimationTargetCompat[] nonAppTargets, DepthController depthController,
|
@NonNull RemoteAnimationTargetCompat[] wallpaperTargets,
|
||||||
|
@NonNull RemoteAnimationTargetCompat[] nonAppTargets,
|
||||||
|
@Nullable DepthController depthController,
|
||||||
PendingAnimation out) {
|
PendingAnimation out) {
|
||||||
RecentsView recentsView = v.getRecentsView();
|
RecentsView recentsView = v.getRecentsView();
|
||||||
boolean isQuickSwitch = v.isEndQuickswitchCuj();
|
boolean isQuickSwitch = v.isEndQuickswitchCuj();
|
||||||
@@ -418,15 +422,46 @@ public final class TaskViewUtils {
|
|||||||
finishCallback.run();
|
finishCallback.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Legacy version (until shell transitions are enabled) */
|
/**
|
||||||
public static void composeRecentsSplitLaunchAnimatorLegacy(@NonNull Task initialTask,
|
* Legacy version (until shell transitions are enabled)
|
||||||
|
*
|
||||||
|
* If {@param launchingTaskView} is not null, then this will play the tasks launch animation
|
||||||
|
* from the position of the GroupedTaskView (when user taps on the TaskView to start it).
|
||||||
|
* Technically this case should be taken care of by
|
||||||
|
* {@link #composeRecentsSplitLaunchAnimatorLegacy()} below, but the way we launch tasks whether
|
||||||
|
* it's a single task or multiple tasks results in different entry-points.
|
||||||
|
*
|
||||||
|
* If it is null, then it will simply fade in the starting apps and fade out launcher (for the
|
||||||
|
* case where launcher handles animating starting split tasks from app icon) */
|
||||||
|
public static void composeRecentsSplitLaunchAnimatorLegacy(
|
||||||
|
@Nullable GroupedTaskView launchingTaskView,
|
||||||
|
@NonNull Task initialTask,
|
||||||
@NonNull Task secondTask, @NonNull RemoteAnimationTargetCompat[] appTargets,
|
@NonNull Task secondTask, @NonNull RemoteAnimationTargetCompat[] appTargets,
|
||||||
@NonNull RemoteAnimationTargetCompat[] wallpaperTargets,
|
@NonNull RemoteAnimationTargetCompat[] wallpaperTargets,
|
||||||
@NonNull RemoteAnimationTargetCompat[] nonAppTargets,
|
@NonNull RemoteAnimationTargetCompat[] nonAppTargets,
|
||||||
|
@NonNull StateManager stateManager,
|
||||||
|
@Nullable DepthController depthController,
|
||||||
@NonNull Runnable finishCallback) {
|
@NonNull Runnable finishCallback) {
|
||||||
|
if (launchingTaskView != null) {
|
||||||
|
AnimatorSet animatorSet = new AnimatorSet();
|
||||||
|
RecentsView recentsView = launchingTaskView.getRecentsView();
|
||||||
|
animatorSet.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
super.onAnimationEnd(animation);
|
||||||
|
finishCallback.run();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
composeRecentsLaunchAnimator(animatorSet, launchingTaskView,
|
||||||
|
appTargets, wallpaperTargets, nonAppTargets,
|
||||||
|
true, stateManager,
|
||||||
|
recentsView, depthController);
|
||||||
|
animatorSet.start();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final ArrayList<SurfaceControl> openingTargets = new ArrayList<>();
|
final ArrayList<SurfaceControl> openingTargets = new ArrayList<>();
|
||||||
final ArrayList<SurfaceControl> closingTargets = new ArrayList<>();
|
final ArrayList<SurfaceControl> closingTargets = new ArrayList<>();
|
||||||
|
|
||||||
for (RemoteAnimationTargetCompat appTarget : appTargets) {
|
for (RemoteAnimationTargetCompat appTarget : appTargets) {
|
||||||
final int taskId = appTarget.taskInfo != null ? appTarget.taskInfo.taskId : -1;
|
final int taskId = appTarget.taskInfo != null ? appTarget.taskInfo.taskId : -1;
|
||||||
final int mode = appTarget.mode;
|
final int mode = appTarget.mode;
|
||||||
@@ -490,7 +525,7 @@ public final class TaskViewUtils {
|
|||||||
@NonNull RemoteAnimationTargetCompat[] wallpaperTargets,
|
@NonNull RemoteAnimationTargetCompat[] wallpaperTargets,
|
||||||
@NonNull RemoteAnimationTargetCompat[] nonAppTargets, boolean launcherClosing,
|
@NonNull RemoteAnimationTargetCompat[] nonAppTargets, boolean launcherClosing,
|
||||||
@NonNull StateManager stateManager, @NonNull RecentsView recentsView,
|
@NonNull StateManager stateManager, @NonNull RecentsView recentsView,
|
||||||
@NonNull DepthController depthController) {
|
@Nullable DepthController depthController) {
|
||||||
boolean skipLauncherChanges = !launcherClosing;
|
boolean skipLauncherChanges = !launcherClosing;
|
||||||
|
|
||||||
TaskView taskView = findTaskViewToLaunch(recentsView, v, appTargets);
|
TaskView taskView = findTaskViewToLaunch(recentsView, v, appTargets);
|
||||||
|
|||||||
@@ -30,11 +30,18 @@ import android.view.RemoteAnimationAdapter;
|
|||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.window.TransitionInfo;
|
import android.window.TransitionInfo;
|
||||||
|
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.launcher3.statehandlers.DepthController;
|
||||||
|
import com.android.launcher3.statemanager.StateManager;
|
||||||
import com.android.launcher3.util.SplitConfigurationOptions;
|
import com.android.launcher3.util.SplitConfigurationOptions;
|
||||||
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
|
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
|
||||||
import com.android.quickstep.SystemUiProxy;
|
import com.android.quickstep.SystemUiProxy;
|
||||||
import com.android.quickstep.TaskAnimationManager;
|
import com.android.quickstep.TaskAnimationManager;
|
||||||
import com.android.quickstep.TaskViewUtils;
|
import com.android.quickstep.TaskViewUtils;
|
||||||
|
import com.android.quickstep.views.GroupedTaskView;
|
||||||
|
import com.android.quickstep.views.TaskView;
|
||||||
import com.android.systemui.shared.recents.model.Task;
|
import com.android.systemui.shared.recents.model.Task;
|
||||||
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
|
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
|
||||||
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
|
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
|
||||||
@@ -52,23 +59,32 @@ public class SplitSelectStateController {
|
|||||||
|
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final SystemUiProxy mSystemUiProxy;
|
private final SystemUiProxy mSystemUiProxy;
|
||||||
|
private final StateManager mStateManager;
|
||||||
|
private final DepthController mDepthController;
|
||||||
private @StagePosition int mStagePosition;
|
private @StagePosition int mStagePosition;
|
||||||
private Task mInitialTask;
|
private Task mInitialTask;
|
||||||
private Task mSecondTask;
|
private Task mSecondTask;
|
||||||
private Rect mInitialBounds;
|
private Rect mInitialBounds;
|
||||||
private boolean mRecentsAnimationRunning;
|
private boolean mRecentsAnimationRunning;
|
||||||
|
/** If not null, this is the TaskView we want to launch from */
|
||||||
|
@Nullable
|
||||||
|
private GroupedTaskView mLaunchingTaskView;
|
||||||
|
|
||||||
public SplitSelectStateController(Handler handler, SystemUiProxy systemUiProxy) {
|
public SplitSelectStateController(Handler handler, SystemUiProxy systemUiProxy,
|
||||||
|
StateManager stateManager,
|
||||||
|
DepthController depthController) {
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
mSystemUiProxy = systemUiProxy;
|
mSystemUiProxy = systemUiProxy;
|
||||||
|
mStateManager = stateManager;
|
||||||
|
mDepthController = depthController;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To be called after first task selected
|
* To be called after first task selected
|
||||||
*/
|
*/
|
||||||
public void setInitialTaskSelect(Task taskView, @StagePosition int stagePosition,
|
public void setInitialTaskSelect(Task task, @StagePosition int stagePosition,
|
||||||
Rect initialBounds) {
|
Rect initialBounds) {
|
||||||
mInitialTask = taskView;
|
mInitialTask = task;
|
||||||
mStagePosition = stagePosition;
|
mStagePosition = stagePosition;
|
||||||
mInitialBounds = initialBounds;
|
mInitialBounds = initialBounds;
|
||||||
}
|
}
|
||||||
@@ -76,12 +92,24 @@ public class SplitSelectStateController {
|
|||||||
/**
|
/**
|
||||||
* To be called after second task selected
|
* To be called after second task selected
|
||||||
*/
|
*/
|
||||||
public void setSecondTaskId(Task taskView, Consumer<Boolean> callback) {
|
public void setSecondTaskId(Task task, Consumer<Boolean> callback) {
|
||||||
mSecondTask = taskView;
|
mSecondTask = task;
|
||||||
launchTasks(mInitialTask, mSecondTask, mStagePosition, callback,
|
launchTasks(mInitialTask, mSecondTask, mStagePosition, callback,
|
||||||
false /* freezeTaskList */);
|
false /* freezeTaskList */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To be called when we want to launch split pairs from an existing GroupedTaskView.
|
||||||
|
*/
|
||||||
|
public void launchTasks(GroupedTaskView groupedTaskView,
|
||||||
|
Consumer<Boolean> callback, boolean freezeTaskList) {
|
||||||
|
mLaunchingTaskView = groupedTaskView;
|
||||||
|
TaskView.TaskIdAttributeContainer[] taskIdAttributeContainers =
|
||||||
|
groupedTaskView.getTaskIdAttributeContainers();
|
||||||
|
launchTasks(taskIdAttributeContainers[0].getTask(), taskIdAttributeContainers[1].getTask(),
|
||||||
|
taskIdAttributeContainers[0].getStagePosition(), callback, freezeTaskList);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param stagePosition representing location of task1
|
* @param stagePosition representing location of task1
|
||||||
*/
|
*/
|
||||||
@@ -169,8 +197,9 @@ public class SplitSelectStateController {
|
|||||||
RemoteAnimationTargetCompat[] wallpapers, RemoteAnimationTargetCompat[] nonApps,
|
RemoteAnimationTargetCompat[] wallpapers, RemoteAnimationTargetCompat[] nonApps,
|
||||||
Runnable finishedCallback) {
|
Runnable finishedCallback) {
|
||||||
postAsyncCallback(mHandler,
|
postAsyncCallback(mHandler,
|
||||||
() -> TaskViewUtils.composeRecentsSplitLaunchAnimatorLegacy(mInitialTask,
|
() -> TaskViewUtils.composeRecentsSplitLaunchAnimatorLegacy(
|
||||||
mSecondTask, apps, wallpapers, nonApps, () -> {
|
mLaunchingTaskView, mInitialTask, mSecondTask, apps, wallpapers,
|
||||||
|
nonApps, mStateManager, mDepthController, () -> {
|
||||||
finishedCallback.run();
|
finishedCallback.run();
|
||||||
if (mSuccessCallback != null) {
|
if (mSuccessCallback != null) {
|
||||||
mSuccessCallback.accept(true);
|
mSuccessCallback.accept(true);
|
||||||
@@ -201,6 +230,7 @@ public class SplitSelectStateController {
|
|||||||
mStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
|
mStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
|
||||||
mInitialBounds = null;
|
mInitialBounds = null;
|
||||||
mRecentsAnimationRunning = false;
|
mRecentsAnimationRunning = false;
|
||||||
|
mLaunchingTaskView = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -156,8 +156,8 @@ public class GroupedTaskView extends TaskView {
|
|||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public RunnableList launchTaskAnimated() {
|
public RunnableList launchTaskAnimated() {
|
||||||
getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
|
getRecentsView().getSplitPlaceholder().launchTasks(this /*groupedTaskView*/,
|
||||||
STAGE_POSITION_TOP_OR_LEFT, null /*callback*/,
|
null /*callback*/,
|
||||||
false /* freezeTaskList */);
|
false /* freezeTaskList */);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user