Update animations for TM-QPR: OverviewSplitSelect > Confirmed transition
This change updates the animation for confirming a split.
Includes:
- New timings
- A new interface, SplitAnimationTimings, that centralizes timing values for splitscreen animations
Fixes: 241126570
Test: Manual
Change-Id: I61339964a7254618b368b17f00fda8f5efb53de4
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index f5161aa..bfece6c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -62,6 +62,7 @@
import com.android.launcher3.uioverrides.QuickstepLauncher;
import com.android.launcher3.util.DisplayController;
import com.android.quickstep.util.RecentsAtomicAnimationFactory;
+import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.views.RecentsView;
/**
@@ -79,14 +80,6 @@
private static final int PER_PAGE_SCROLL_DURATION = 150;
private static final int MAX_PAGE_SCROLL_DURATION = 750;
- private static final int OVERVIEW_TO_SPLIT_ACTIONS_FADE_START = 0;
- private static final int OVERVIEW_TO_SPLIT_ACTIONS_FADE_END = 83;
-
- private static final float OVERVIEW_TO_SPLIT_ACTIONS_FADE_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_ACTIONS_FADE_START / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_ACTIONS_FADE_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_ACTIONS_FADE_END / SplitScreenSelectState.ENTER_DURATION;
-
// Due to use of physics, duration may differ between devices so we need to calculate and
// cache the value.
private int mHintToNormalDuration = -1;
@@ -197,9 +190,10 @@
} else if (fromState == NORMAL && toState == ALL_APPS) {
AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mActivity, config);
} else if (fromState == OVERVIEW && toState == OVERVIEW_SPLIT_SELECT) {
+ SplitAnimationTimings timings = SplitAnimationTimings.OVERVIEW_TO_SPLIT;
config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, clampToProgress(LINEAR,
- OVERVIEW_TO_SPLIT_ACTIONS_FADE_START_OFFSET,
- OVERVIEW_TO_SPLIT_ACTIONS_FADE_END_OFFSET));
+ timings.getActionsFadeStartOffset(),
+ timings.getActionsFadeEndOffset()));
}
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
index 2bc3c3e..430053d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
@@ -19,6 +19,7 @@
import android.content.Context;
import com.android.launcher3.Launcher;
+import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.views.RecentsView;
/**
@@ -26,10 +27,6 @@
* pinned and user is selecting the second one
*/
public class SplitScreenSelectState extends OverviewState {
- public static final int ENTER_DURATION = 866;
- public static final int EXIT_DURATION = 500;
- // TODO: Add ability to differentiate between Split > Home and Split > Confirmed timings
-
public SplitScreenSelectState(int id) {
super(id);
}
@@ -47,6 +44,8 @@
@Override
public int getTransitionDuration(Context context, boolean isToState) {
- return isToState ? ENTER_DURATION : EXIT_DURATION;
+ return isToState
+ ? SplitAnimationTimings.ENTER_DURATION
+ : SplitAnimationTimings.ABORT_DURATION;
}
}
diff --git a/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java b/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java
new file mode 100644
index 0000000..40e547b
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/OverviewToSplitTimings.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2022 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.util;
+
+import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
+
+import android.view.animation.Interpolator;
+
+/**
+ * Timings for the Overview > OverviewSplitSelect animation.
+ */
+public class OverviewToSplitTimings implements SplitAnimationTimings {
+ public int getThumbnailFadeToGrayStart() { return 0; }
+ public int getThumbnailFadeToGrayEnd() { return 133; }
+ public int getDockedIconFadeInStart() { return 167; }
+ public int getDockedIconFadeInEnd() { return 250; }
+ public int getStagedRectSlideStart() { return 0; }
+ public int getStagedRectSlideEnd() { return 417; }
+ public int getGridSlideStart() { return 67; }
+ public int getGridSlideStagger() { return 16; }
+ public int getGridSlideDuration() { return 500; }
+ public int getActionsFadeStart() { return 0; }
+ public int getActionsFadeEnd() { return 83; }
+ public int getIconFadeStart() { return 0; }
+ public int getIconFadeEnd() { return 83; }
+ public int getInstructionsContainerFadeInStart() { return 167; }
+ public int getInstructionsContainerFadeInEnd() { return 250; }
+ public int getInstructionsTextFadeInStart() { return 217; }
+ public int getInstructionsTextFadeInEnd() { return 300; }
+ public int getInstructionsUnfoldStart() { return 167; }
+ public int getInstructionsUnfoldEnd() { return 500; }
+
+ public int getDuration() { return ENTER_DURATION; }
+ public Interpolator getStagedRectSlideInterpolator() { return DEACCEL_2; }
+
+ public float getGridSlideStartOffset() {
+ return (float) getGridSlideStart() / getDuration();
+ }
+ public float getGridSlideStaggerOffset() {
+ return (float) getGridSlideStagger() / getDuration();
+ }
+ public float getGridSlideDurationOffset() {
+ return (float) getGridSlideDuration() / getDuration();
+ }
+ public float getActionsFadeStartOffset() {
+ return (float) getActionsFadeStart() / getDuration();
+ }
+ public float getActionsFadeEndOffset() {
+ return (float) getActionsFadeEnd() / getDuration();
+ }
+ public float getIconFadeStartOffset() {
+ return (float) getIconFadeStart() / getDuration();
+ }
+ public float getIconFadeEndOffset() {
+ return (float) getIconFadeEnd() / getDuration();
+ }
+ public float getInstructionsContainerFadeInStartOffset() {
+ return (float) getInstructionsContainerFadeInStart() / getDuration();
+ }
+ public float getInstructionsContainerFadeInEndOffset() {
+ return (float) getInstructionsContainerFadeInEnd() / getDuration();
+ }
+ public float getInstructionsTextFadeInStartOffset() {
+ return (float) getInstructionsTextFadeInStart() / getDuration();
+ }
+ public float getInstructionsTextFadeInEndOffset() {
+ return (float) getInstructionsTextFadeInEnd() / getDuration();
+ }
+ public float getInstructionsUnfoldStartOffset() {
+ return (float) getInstructionsUnfoldStart() / getDuration();
+ }
+ public float getInstructionsUnfoldEndOffset() {
+ return (float) getInstructionsUnfoldEnd() / getDuration();
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
new file mode 100644
index 0000000..c6f7fb1
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationTimings.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 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.util;
+
+import android.view.animation.Interpolator;
+
+/**
+ * An interface that supports the centralization of timing information for splitscreen animations.
+ */
+public interface SplitAnimationTimings {
+ int ENTER_DURATION = 866;
+ int ABORT_DURATION = 500;
+ int CONFIRM_DURATION = 383;
+
+ SplitAnimationTimings OVERVIEW_TO_SPLIT = new OverviewToSplitTimings();
+ SplitAnimationTimings SPLIT_TO_CONFIRM = new SplitToConfirmTimings();
+
+ // Shared methods
+ int getDuration();
+ int getThumbnailFadeToGrayStart();
+ int getThumbnailFadeToGrayEnd();
+ int getDockedIconFadeInStart();
+ int getDockedIconFadeInEnd();
+ int getStagedRectSlideStart();
+ int getStagedRectSlideEnd();
+ Interpolator getStagedRectSlideInterpolator();
+ default float getThumbnailFadeToGrayStartOffset() {
+ return (float) getThumbnailFadeToGrayStart() / getDuration();
+ }
+ default float getThumbnailFadeToGrayEndOffset() {
+ return (float) getThumbnailFadeToGrayEnd() / getDuration();
+ }
+ default float getDockedIconFadeInStartOffset() {
+ return (float) getDockedIconFadeInStart() / getDuration();
+ }
+ default float getDockedIconFadeInEndOffset() {
+ return (float) getDockedIconFadeInEnd() / getDuration();
+ }
+ default float getStagedRectSlideStartOffset() {
+ return (float) getStagedRectSlideStart() / getDuration();
+ }
+ default float getStagedRectSlideEndOffset() {
+ return (float) getStagedRectSlideEnd() / getDuration();
+ }
+
+ // Defaults for OverviewToSplit
+ default float getGridSlideStartOffset() { return 0; }
+ default float getGridSlideStaggerOffset() { return 0; }
+ default float getGridSlideDurationOffset() { return 0; }
+ default float getActionsFadeStartOffset() { return 0; }
+ default float getActionsFadeEndOffset() { return 0; }
+ default float getIconFadeStartOffset() { return 0; }
+ default float getIconFadeEndOffset() { return 0; }
+ default float getInstructionsContainerFadeInStartOffset() { return 0; }
+ default float getInstructionsContainerFadeInEndOffset() { return 0; }
+ default float getInstructionsTextFadeInStartOffset() { return 0; }
+ default float getInstructionsTextFadeInEndOffset() { return 0; }
+ default float getInstructionsUnfoldStartOffset() { return 0; }
+ default float getInstructionsUnfoldEndOffset() { return 0; }
+
+ // Defaults for SplitToConfirm
+ default float getInstructionsFadeStartOffset() { return 0; }
+ default float getInstructionsFadeEndOffset() { return 0; }
+}
+
diff --git a/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
new file mode 100644
index 0000000..2eb0941
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/util/SplitToConfirmTimings.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 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.util;
+
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+
+import android.view.animation.Interpolator;
+
+/**
+ * Timings for the OverviewSplitSelect > confirmed animation.
+ */
+public class SplitToConfirmTimings implements SplitAnimationTimings {
+ public int getThumbnailFadeToGrayStart() { return 0; }
+ public int getThumbnailFadeToGrayEnd() { return 133; }
+ public int getDockedIconFadeInStart() { return 167; }
+ public int getDockedIconFadeInEnd() { return 250; }
+ public int getStagedRectSlideStart() { return 0; }
+ public int getStagedRectSlideEnd() { return 383; }
+ public int getInstructionsFadeStart() { return 0; }
+ public int getInstructionsFadeEnd() { return 67; }
+
+ public int getDuration() { return CONFIRM_DURATION; }
+ public Interpolator getStagedRectSlideInterpolator() { return LINEAR; }
+
+ public float getInstructionsFadeStartOffset() {
+ return (float) getInstructionsFadeStart() / getDuration();
+ }
+ public float getInstructionsFadeEndOffset() {
+ return (float) getInstructionsFadeEnd() / getDuration();
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
index c211d7a..1d58748 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
@@ -2,7 +2,6 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
import static com.android.launcher3.anim.Interpolators.ACCEL;
-import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.anim.Interpolators.INSTANT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
@@ -31,10 +30,10 @@
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.touch.PagedOrientationHandler;
-import com.android.launcher3.uioverrides.states.SplitScreenSelectState;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.util.MultiValueUpdateListener;
+import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.util.TaskCornerRadius;
import com.android.systemui.shared.system.QuickStepContract;
@@ -44,38 +43,14 @@
* which will have the thumbnail from the provided existing TaskView overlaying the taskview itself.
*
* Can then animate the taskview using
- * {@link #addAnimation(PendingAnimation, RectF, Rect, boolean, boolean)}
+ * {@link #addStagingAnimation(PendingAnimation, RectF, Rect, boolean, boolean)} or
+ * {@link #addConfirmAnimation(PendingAnimation, RectF, Rect, boolean, boolean)}
* giving a starting and ending bounds. Currently this is set to use the split placeholder view,
* but it could be generified.
*
* TODO: Figure out how to copy thumbnail data from existing TaskView to this view.
*/
public class FloatingTaskView extends FrameLayout {
- private static final int OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START = 0;
- private static final int OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END = 133;
- private static final int OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_START = 167;
- private static final int OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_END = 250;
- private static final int OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START = 0;
- private static final int OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END = 417;
-
- private static final float OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_END
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END
- / SplitScreenSelectState.ENTER_DURATION;
public static final FloatProperty<FloatingTaskView> PRIMARY_TRANSLATE_OFFSCREEN =
new FloatProperty<FloatingTaskView>("floatingTaskPrimaryTranslateOffscreen") {
@@ -236,8 +211,34 @@
layout(left, lp.topMargin, left + lp.width, lp.topMargin + lp.height);
}
- public void addAnimation(PendingAnimation animation, RectF startingBounds, Rect endBounds,
- boolean fadeWithThumbnail, boolean isStagedTask) {
+ /**
+ * Animates a FloatingTaskThumbnailView and its overlapping SplitPlaceholderView when a split
+ * is staged.
+ */
+ public void addStagingAnimation(PendingAnimation animation, RectF startingBounds,
+ Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask) {
+ addAnimation(animation, startingBounds, endBounds, fadeWithThumbnail, isStagedTask,
+ SplitAnimationTimings.OVERVIEW_TO_SPLIT);
+ }
+
+ /**
+ * Animates the FloatingTaskThumbnailView and SplitPlaceholderView for the two thumbnails
+ * when a split is confirmed.
+ */
+ public void addConfirmAnimation(PendingAnimation animation, RectF startingBounds,
+ Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask) {
+ addAnimation(animation, startingBounds, endBounds, fadeWithThumbnail, isStagedTask,
+ SplitAnimationTimings.SPLIT_TO_CONFIRM);
+ }
+
+ /**
+ * Sets up and builds a split staging animation.
+ * Called by {@link #addStagingAnimation(PendingAnimation, RectF, Rect, boolean, boolean)} and
+ * {@link #addConfirmAnimation(PendingAnimation, RectF, Rect, boolean, boolean)}.
+ */
+ public void addAnimation(PendingAnimation animation, RectF startingBounds,
+ Rect endBounds, boolean fadeWithThumbnail, boolean isStagedTask,
+ SplitAnimationTimings timings) {
mFullscreenParams.setIsStagedTask(isStagedTask);
final BaseDragLayer dragLayer = mActivity.getDragLayer();
int[] dragLayerBounds = new int[2];
@@ -251,49 +252,54 @@
RectF floatingTaskViewBounds = new RectF();
if (fadeWithThumbnail) {
- // This code block runs when animating from Overview > OverviewSplitSelect
- // And for the second thumbnail on confirm
+ // This code block runs for the placeholder view during Overview > OverviewSplitSelect
+ // and for the selected (secondary) thumbnail during OverviewSplitSelect > Confirmed
// FloatingTaskThumbnailView: thumbnail fades out to transparent
animation.setViewAlpha(mThumbnailView, 0, clampToProgress(LINEAR,
- OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START_OFFSET,
- OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END_OFFSET));
+ timings.getThumbnailFadeToGrayStartOffset(),
+ timings.getThumbnailFadeToGrayEndOffset()));
- // SplitPlaceholderView: gray background fades in at the same time, then new icon fades
- // in
+ // SplitPlaceholderView: gray background fades in at same time, then new icon fades in
animation.setViewAlpha(mSplitPlaceholderView, 1, clampToProgress(LINEAR,
- OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_START_OFFSET,
- OVERVIEW_TO_SPLIT_THUMBNAIL_FADE_TO_GRAY_END_OFFSET));
+ timings.getThumbnailFadeToGrayStartOffset(),
+ timings.getThumbnailFadeToGrayEndOffset()));
animation.setViewAlpha(mSplitPlaceholderView.getIconView(), 1, clampToProgress(
- LINEAR, OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_START_OFFSET,
- OVERVIEW_TO_SPLIT_DOCKED_ICON_FADE_IN_END_OFFSET));
+ LINEAR,
+ timings.getDockedIconFadeInStartOffset(),
+ timings.getDockedIconFadeInEndOffset()));
} else if (isStagedTask) {
- // This code block runs when animating from Normal > OverviewSplitSelect
- // and for the first thumbnail on confirm
+ // This code block runs for the placeholder view during Normal > OverviewSplitSelect
+ // and for the placeholder (primary) thumbnail during OverviewSplitSelect > Confirmed
- // Fade in the placeholder view when split is initiated from homescreen / all apps
+ // Fade in the placeholder view during Normal > OverviewSplitSelect
if (mSplitPlaceholderView.getAlpha() == 0) {
animation.setViewAlpha(mSplitPlaceholderView, 0.3f, INSTANT);
animation.setViewAlpha(mSplitPlaceholderView, 1, ACCEL);
}
+
+ // No-op for placeholder during OverviewSplitSelect > Confirmed, alpha should be set
}
+
MultiValueUpdateListener listener = new MultiValueUpdateListener() {
// SplitPlaceholderView: rectangle translates and stretches to new position
final FloatProp mDx = new FloatProp(0, prop.dX, 0, animDuration,
- clampToProgress(DEACCEL_2, OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET,
- OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET));
+ clampToProgress(timings.getStagedRectSlideInterpolator(),
+ timings.getStagedRectSlideStartOffset(),
+ timings.getStagedRectSlideEndOffset()));
final FloatProp mDy = new FloatProp(0, prop.dY, 0, animDuration,
- clampToProgress(DEACCEL_2, OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET,
- OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET));
+ clampToProgress(timings.getStagedRectSlideInterpolator(),
+ timings.getStagedRectSlideStartOffset(),
+ timings.getStagedRectSlideEndOffset()));
final FloatProp mTaskViewScaleX = new FloatProp(1f, prop.finalTaskViewScaleX, 0,
- animDuration, clampToProgress(DEACCEL_2,
- OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET,
- OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET));
+ animDuration, clampToProgress(timings.getStagedRectSlideInterpolator(),
+ timings.getStagedRectSlideStartOffset(),
+ timings.getStagedRectSlideEndOffset()));
final FloatProp mTaskViewScaleY = new FloatProp(1f, prop.finalTaskViewScaleY, 0,
- animDuration, clampToProgress(DEACCEL_2,
- OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_START_OFFSET,
- OVERVIEW_TO_SPLIT_STAGED_RECT_SLIDE_END_OFFSET));
+ animDuration, clampToProgress(timings.getStagedRectSlideInterpolator(),
+ timings.getStagedRectSlideStartOffset(),
+ timings.getStagedRectSlideEndOffset()));
@Override
public void onUpdate(float percent, boolean initOnly) {
// Calculate the icon position.
@@ -305,6 +311,7 @@
update(floatingTaskViewBounds, percent);
}
};
+
transitionAnimator.addUpdateListener(listener);
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 8da08b4..3f2681c 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -39,7 +39,7 @@
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.anim.Interpolators.OVERSHOOT_0_85;
+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_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
@@ -140,7 +140,6 @@
import com.android.launcher3.statemanager.StatefulActivity;
import com.android.launcher3.touch.OverScroll;
import com.android.launcher3.touch.PagedOrientationHandler;
-import com.android.launcher3.uioverrides.states.SplitScreenSelectState;
import com.android.launcher3.util.DynamicResource;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.IntSet;
@@ -173,6 +172,7 @@
import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RecentsOrientedState;
+import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.util.SplitScreenBounds;
import com.android.quickstep.util.SplitSelectStateController;
import com.android.quickstep.util.SurfaceTransaction;
@@ -417,54 +417,6 @@
private static final float ANIMATION_DISMISS_PROGRESS_MIDPOINT = 0.5f;
private static final float END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.75f;
- private static final int OVERVIEW_TO_SPLIT_THUMBNAIL_SLIDE_START = 67;
- private static final int OVERVIEW_TO_SPLIT_THUMBNAIL_SLIDE_OFFSET = 16;
- private static final int SPRING_DISMISS_TRANSLATION_DURATION = 500;
-
- private static final float INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET =
- (float) OVERVIEW_TO_SPLIT_THUMBNAIL_SLIDE_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET =
- (float) OVERVIEW_TO_SPLIT_THUMBNAIL_SLIDE_OFFSET
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float END_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET =
- (float) SPRING_DISMISS_TRANSLATION_DURATION
- / SplitScreenSelectState.ENTER_DURATION;
-
- private static final int OVERVIEW_TO_SPLIT_ICON_FADE_START = 0;
- private static final int OVERVIEW_TO_SPLIT_ICON_FADE_END = 83;
- private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_START = 167;
- private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_END = 250;
- private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_START = 217;
- private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_END = 300;
- private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_START = 167;
- private static final int OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_END = 500;
-
- private static final float OVERVIEW_TO_SPLIT_ICON_FADE_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_ICON_FADE_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_ICON_FADE_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_ICON_FADE_END
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_END
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_END
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_START_OFFSET =
- (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_START
- / SplitScreenSelectState.ENTER_DURATION;
- private static final float OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_END_OFFSET =
- (float) OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_END
- / SplitScreenSelectState.ENTER_DURATION;
-
private static final float SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE = 0.15f;
protected final RecentsOrientedState mOrientationState;
@@ -2856,27 +2808,28 @@
mOrientationHandler.getInitialSplitPlaceholderBounds(mSplitPlaceholderSize,
mSplitPlaceholderInset, mActivity.getDeviceProfile(),
mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
+ SplitAnimationTimings timings = SplitAnimationTimings.OVERVIEW_TO_SPLIT;
RectF startingTaskRect = new RectF();
if (mSplitHiddenTaskView != null) {
// Split staging is initiated
mSplitHiddenTaskView.setThumbnailVisibility(INVISIBLE);
anim.setViewAlpha(mSplitHiddenTaskView.getIconView(), 0, clampToProgress(LINEAR,
- OVERVIEW_TO_SPLIT_ICON_FADE_START_OFFSET,
- OVERVIEW_TO_SPLIT_ICON_FADE_END_OFFSET));
+ timings.getIconFadeStartOffset(),
+ timings.getIconFadeEndOffset()));
mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
mSplitHiddenTaskView.getThumbnail(),
mSplitHiddenTaskView.getThumbnail().getThumbnail(),
mSplitHiddenTaskView.getIconView().getDrawable(), startingTaskRect);
mFirstFloatingTaskView.setAlpha(1);
- mFirstFloatingTaskView.addAnimation(anim, startingTaskRect, mTempRect,
+ mFirstFloatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
true /* fadeWithThumbnail */, true /* isStagedTask */);
} else {
mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
mSplitSelectSource.view, null /* thumbnail */,
mSplitSelectSource.drawable, startingTaskRect);
mFirstFloatingTaskView.setAlpha(1);
- mFirstFloatingTaskView.addAnimation(anim, startingTaskRect, mTempRect,
+ mFirstFloatingTaskView.addStagingAnimation(anim, startingTaskRect, mTempRect,
false /* fadeWithThumbnail */, true /* isStagedTask */);
}
@@ -2884,15 +2837,15 @@
mSplitInstructionsView = SplitInstructionsView.getSplitInstructionsView(mActivity);
mSplitInstructionsView.setAlpha(0);
anim.setViewAlpha(mSplitInstructionsView, 1, clampToProgress(LINEAR,
- OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_START_OFFSET,
- OVERVIEW_TO_SPLIT_INSTRUCTIONS_CONTAINER_FADE_IN_END_OFFSET));
+ timings.getInstructionsContainerFadeInStartOffset(),
+ timings.getInstructionsContainerFadeInEndOffset()));
anim.setViewAlpha(mSplitInstructionsView.getTextView(), 1, clampToProgress(LINEAR,
- OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_START_OFFSET,
- OVERVIEW_TO_SPLIT_INSTRUCTIONS_TEXT_FADE_IN_END_OFFSET));
+ timings.getInstructionsTextFadeInStartOffset(),
+ timings.getInstructionsTextFadeInEndOffset()));
anim.addFloat(mSplitInstructionsView, mSplitInstructionsView.UNFOLD, 0.1f, 1,
clampToProgress(EMPHASIZED_DECELERATE,
- OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_START_OFFSET,
- OVERVIEW_TO_SPLIT_INSTRUCTIONS_UNFOLD_END_OFFSET));
+ timings.getInstructionsUnfoldStartOffset(),
+ timings.getInstructionsUnfoldEndOffset()));
InteractionJankMonitorWrapper.begin(this,
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "First tile selected");
@@ -3181,24 +3134,26 @@
: distanceFromDismissedTask;
// Set timings based on if user is initiating splitscreen on the focused task,
// or splitting/dismissing some other task.
+ SplitAnimationTimings timings = SplitAnimationTimings.OVERVIEW_TO_SPLIT;
float animationStartProgress = isStagingFocusedTask
? Utilities.boundToRange(
- INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- + ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- * staggerColumn, 0f, dismissTranslationInterpolationEnd)
+ timings.getGridSlideStartOffset()
+ + (timings.getGridSlideStaggerOffset() * staggerColumn),
+ 0f,
+ dismissTranslationInterpolationEnd)
: Utilities.boundToRange(
INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
+ ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
* staggerColumn, 0f, dismissTranslationInterpolationEnd);
float animationEndProgress = isStagingFocusedTask
? Utilities.boundToRange(
- INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- + END_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- + ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET
- * staggerColumn,
- 0f, dismissTranslationInterpolationEnd)
+ timings.getGridSlideStartOffset()
+ + (timings.getGridSlideStaggerOffset() * staggerColumn)
+ + timings.getGridSlideDurationOffset(),
+ 0f,
+ dismissTranslationInterpolationEnd)
: dismissTranslationInterpolationEnd;
- Interpolator dismissInterpolator = isStagingFocusedTask ? OVERSHOOT_0_85 : LINEAR;
+ Interpolator dismissInterpolator = isStagingFocusedTask ? OVERSHOOT_0_75 : LINEAR;
if (taskView == nextFocusedTaskView) {
// Enlarge the task to be focused next, and translate into focus position.
@@ -4214,9 +4169,9 @@
// TODO(194414938) starting bounds seem slightly off, investigate
Rect firstTaskStartingBounds = new Rect();
Rect firstTaskEndingBounds = mTempRect;
- int duration = mActivity.getStateManager().getState().getTransitionDuration(mActivity,
- false /* isToState */);
- PendingAnimation pendingAnimation = new PendingAnimation(duration);
+ PendingAnimation pendingAnimation =
+ new PendingAnimation(SplitAnimationTimings.CONFIRM_DURATION);
+ SplitAnimationTimings timings = SplitAnimationTimings.SPLIT_TO_CONFIRM;
int halfDividerSize = getResources()
.getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;
@@ -4226,7 +4181,7 @@
secondTaskEndingBounds);
mFirstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds);
- mFirstFloatingTaskView.addAnimation(pendingAnimation,
+ mFirstFloatingTaskView.addConfirmAnimation(pendingAnimation,
new RectF(firstTaskStartingBounds), firstTaskEndingBounds,
false /* fadeWithThumbnail */, true /* isStagedTask */);
@@ -4234,8 +4189,13 @@
thumbnailView, thumbnailView.getThumbnail(),
iconView.getDrawable(), secondTaskStartingBounds);
mSecondFloatingTaskView.setAlpha(1);
- mSecondFloatingTaskView.addAnimation(pendingAnimation, secondTaskStartingBounds,
+ mSecondFloatingTaskView.addConfirmAnimation(pendingAnimation, secondTaskStartingBounds,
secondTaskEndingBounds, true /* fadeWithThumbnail */, false /* isStagedTask */);
+
+ pendingAnimation.setViewAlpha(mSplitInstructionsView, 0, clampToProgress(LINEAR,
+ timings.getInstructionsFadeStartOffset(),
+ timings.getInstructionsFadeEndOffset()));
+
pendingAnimation.addEndListener(aBoolean -> {
mSplitSelectStateController.launchSplitTasks(
aBoolean1 -> RecentsView.this.resetFromSplitSelectionState());
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index d900c90..b55a1e4 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -83,7 +83,7 @@
EXAGGERATED_EASE = new PathInterpolator(exaggeratedEase);
}
- public static final Interpolator OVERSHOOT_0_85 = new OvershootInterpolator(0.85f);
+ public static final Interpolator OVERSHOOT_0_75 = new OvershootInterpolator(0.75f);
public static final Interpolator OVERSHOOT_1_2 = new OvershootInterpolator(1.2f);
public static final Interpolator OVERSHOOT_1_7 = new OvershootInterpolator(1.7f);