Loading quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java +3 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,9 @@ public class QuickstepAtomicAnimationFactory extends AllAppsSwipeController.applyAllAppsToNormalConfig(mActivity, config); } else if (fromState == NORMAL && toState == ALL_APPS) { AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mActivity, config); } else if (fromState == OVERVIEW && toState == OVERVIEW_SPLIT_SELECT) { config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, clampToProgress(LINEAR, 0, 0.167f)); } } } quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java +9 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.launcher3.uioverrides.states; import android.content.Context; import com.android.launcher3.Launcher; import com.android.quickstep.views.RecentsView; Loading @@ -24,6 +26,8 @@ import com.android.quickstep.views.RecentsView; * pinned and user is selecting the second one */ public class SplitScreenSelectState extends OverviewState { private static final int OVERVIEW_SPLIT_SELECT_SLIDE_IN_DURATION = 500; public SplitScreenSelectState(int id) { super(id); } Loading @@ -38,4 +42,9 @@ public class SplitScreenSelectState extends OverviewState { RecentsView recentsView = launcher.getOverviewPanel(); return recentsView.getSplitSelectTranslation(); } @Override public int getTransitionDuration(Context context, boolean isToState) { return OVERVIEW_SPLIT_SELECT_SLIDE_IN_DURATION; } } quickstep/src/com/android/quickstep/views/FloatingTaskView.java +18 −8 Original line number Diff line number Diff line Loading @@ -2,8 +2,9 @@ package com.android.quickstep.views; 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_3; import static com.android.launcher3.anim.Interpolators.FASTER_OUT_SLOWER_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.clampToProgress; import android.animation.ValueAnimator; import android.content.Context; Loading Loading @@ -200,10 +201,16 @@ public class FloatingTaskView extends FrameLayout { RectF floatingTaskViewBounds = new RectF(); if (fadeWithThumbnail) { animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ALPHA_FLOAT, 0, 1, ACCEL); // FloatingTaskThumbnailView: thumbnail fades out to transparent animation.addFloat(mThumbnailView, LauncherAnimUtils.VIEW_ALPHA, 1, 0, DEACCEL_3); 1, 0, clampToProgress(LINEAR, 0, 0.267f)); // SplitPlaceholderView: gray background fades in at the same time, then new icon fades // in animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ALPHA_FLOAT, 0, 1, clampToProgress(LINEAR, 0, 0.267f)); animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ICON_ALPHA, 0, 1, clampToProgress(LINEAR, 0.333f, 0.5f)); } else if (isStagedTask) { // Fade in the placeholder view when split is initiated from homescreen / all apps // icons. Loading @@ -214,12 +221,15 @@ public class FloatingTaskView extends FrameLayout { } MultiValueUpdateListener listener = new MultiValueUpdateListener() { final FloatProp mDx = new FloatProp(0, prop.dX, 0, animDuration, LINEAR); final FloatProp mDy = new FloatProp(0, prop.dY, 0, animDuration, LINEAR); // SplitPlaceholderView: rectangle translates and stretches to new position final FloatProp mDx = new FloatProp(0, prop.dX, 0, animDuration, clampToProgress(FASTER_OUT_SLOWER_IN, 0, 0.833f)); final FloatProp mDy = new FloatProp(0, prop.dY, 0, animDuration, clampToProgress(FASTER_OUT_SLOWER_IN, 0, 0.833f)); final FloatProp mTaskViewScaleX = new FloatProp(1f, prop.finalTaskViewScaleX, 0, animDuration, LINEAR); animDuration, clampToProgress(FASTER_OUT_SLOWER_IN, 0, 0.833f)); final FloatProp mTaskViewScaleY = new FloatProp(1f, prop.finalTaskViewScaleY, 0, animDuration, LINEAR); animDuration, clampToProgress(FASTER_OUT_SLOWER_IN, 0, 0.833f)); @Override public void onUpdate(float percent, boolean initOnly) { // Calculate the icon position. Loading quickstep/src/com/android/quickstep/views/RecentsView.java +77 −15 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.ACCEL_0_75; import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL_2; import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE; 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; Loading Loading @@ -113,6 +114,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.core.graphics.ColorUtils; import androidx.dynamicanimation.animation.SpringForce; import com.android.launcher3.BaseActivity; import com.android.launcher3.BaseActivity.MultiWindowModeChangedListener; Loading @@ -125,6 +127,7 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.anim.SpringAnimationBuilder; import com.android.launcher3.anim.SpringProperty; import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.config.FeatureFlags; Loading Loading @@ -442,6 +445,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T private static final float ANIMATION_DISMISS_PROGRESS_MIDPOINT = 0.5f; private static final float END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.75f; private static final float INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.133f; private static final float ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.033f; private static final float SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE = 0.15f; protected final RecentsOrientedState mOrientationState; Loading Loading @@ -2825,7 +2831,20 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T RectF startingTaskRect = new RectF(); if (mSplitHiddenTaskView != null) { mSplitHiddenTaskView.setVisibility(INVISIBLE); // Split staging is initiated, hide the original TaskView except for the icon (which // needs to animate out over time) // If needed, visibility should be toggled back on in resetFromSplitSelectionState(). for (int i = 0; i < mSplitHiddenTaskView.getChildCount(); i++) { View child = mSplitHiddenTaskView.getChildAt(i); if (child != mSplitHiddenTaskView.mIconView) { child.setVisibility(INVISIBLE); } } // Icon animates out over time anim.addFloat(mSplitHiddenTaskView, TaskView.ICON_ALPHA, 1, 0, clampToProgress(LINEAR, 0, 0.167f)); mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity, mSplitHiddenTaskView.getThumbnail(), mSplitHiddenTaskView.getThumbnail().getThumbnail(), Loading @@ -2842,9 +2861,15 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T false /* fadeWithThumbnail */, true /* isStagedTask */); } // SplitInstructionsView: animate in mSplitInstructionsView = SplitInstructionsView.getSplitInstructionsView(mActivity); mSplitInstructionsView.setAlpha(0); anim.addFloat(mSplitInstructionsView, SplitInstructionsView.ALPHA_FLOAT, 0, 1, ACCEL); anim.addFloat(mSplitInstructionsView, SplitInstructionsView.CONTAINER_ALPHA, 0, 1, clampToProgress(LINEAR, 0, 0.167f)); anim.addFloat(mSplitInstructionsView, SplitInstructionsView.TEXT_ALPHA, 0, 1, clampToProgress(LINEAR, 0.1f, 0.267f)); anim.addFloat(mSplitInstructionsView, mSplitInstructionsView.UNFOLD, 0.1f, 1, clampToProgress(EMPHASIZED_DECELERATE, 0, 0.667f)); InteractionJankMonitorWrapper.begin(this, InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "First tile selected"); Loading Loading @@ -3124,11 +3149,22 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T // Animate task with index >= dismissed index and in the same row as the // dismissed index or next focused index. Offset successive task dismissal // durations for a staggered effect. float animationStartProgress = Utilities.boundToRange( distanceFromDismissedTask++; // If user is initiating splitscreen from the focused (large) task, we use a // spring-based animation and timings. For other, smaller, repositions, we currently // fall back on a less complicated linear animation and timings. float animationStartProgress = isFocusedTaskDismissed && nextFocusedTaskView == null ? Utilities.boundToRange( INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * (int) Math.ceil(distanceFromDismissedTask / 2f), 0f, dismissTranslationInterpolationEnd) : Utilities.boundToRange( INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * ++distanceFromDismissedTask, 0f, * distanceFromDismissedTask, 0f, dismissTranslationInterpolationEnd); if (taskView == nextFocusedTaskView) { // Enlarge the task to be focused next, and translate into focus position. float scale = mTaskWidth / (float) mLastComputedGridTaskSize.width(); Loading Loading @@ -3163,8 +3199,31 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T primaryTranslation += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize; } } // Transitioning to split select -- set up staggered spring animation for // other TaskViews. Animator taskSlideIn = new SpringAnimationBuilder(taskView.mActivity) .setDampingRatio(0.85f) .setStiffness(SpringForce.STIFFNESS_LOW) .setEndValue(mIsRtl ? primaryTranslation : -primaryTranslation) .setStartValue( taskView.getPrimaryDismissTranslationProperty() .get(taskView) ) .build(taskView, taskView.getPrimaryDismissTranslationProperty()); long taskSlideInDuration = taskSlideIn.getDuration(); anim.add(taskSlideIn); taskSlideIn .setDuration(taskSlideInDuration) .setStartDelay( Math.round(animationStartProgress * anim.getDuration())); } else { // Task was dismissed individually -- translate other TaskViews to fill the // vacant space. // TODO (b/242075836): This dismiss animation uses a linear transition. // When the above bug is fixed, it can use the same (nicer) spring // transition as the focused task split case above. anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? primaryTranslation : -primaryTranslation, clampToProgress(LINEAR, animationStartProgress, Loading @@ -3172,6 +3231,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T } } } } if (needsCurveUpdates) { anim.addOnFrameCallback(this::updateCurveProperties); Loading @@ -3189,7 +3249,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T final boolean finalCloseGapBetweenClearAll = closeGapBetweenClearAll; final boolean finalSnapToLastTask = snapToLastTask; final boolean finalIsFocusedTaskDismissed = isFocusedTaskDismissed; mPendingAnimation.addEndListener(new Consumer<Boolean>() { Consumer endConsumer = new Consumer<Boolean>() { @Override public void accept(Boolean success) { if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile Loading Loading @@ -3399,7 +3460,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T onDismissAnimationEnds(); mPendingAnimation = null; } }); }; mPendingAnimation.addListener(AnimatorListeners.forEndCallback(endConsumer)); return anim; } Loading Loading @@ -4220,7 +4283,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T resetTaskVisuals(); mSplitHiddenTaskViewIndex = -1; if (mSplitHiddenTaskView != null) { mSplitHiddenTaskView.setVisibility(VISIBLE); mSplitHiddenTaskView = null; } } Loading quickstep/src/com/android/quickstep/views/SplitInstructionsView.java +33 −2 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatTextView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; Loading @@ -40,9 +41,10 @@ import com.android.launcher3.util.DisplayController; */ public class SplitInstructionsView extends FrameLayout { private final StatefulActivity mLauncher; private AppCompatTextView mTextView; public static final FloatProperty<SplitInstructionsView> ALPHA_FLOAT = new FloatProperty<SplitInstructionsView>("SplitInstructionsAlpha") { public static final FloatProperty<SplitInstructionsView> CONTAINER_ALPHA = new FloatProperty<SplitInstructionsView>("SplitInstructionsContainerAlpha") { @Override public void setValue(SplitInstructionsView splitInstructionsView, float v) { splitInstructionsView.setVisibility(v != 0 ? VISIBLE : GONE); Loading @@ -55,6 +57,32 @@ public class SplitInstructionsView extends FrameLayout { } }; public static final FloatProperty<SplitInstructionsView> UNFOLD = new FloatProperty<SplitInstructionsView>("SplitInstructionsUnfold") { @Override public void setValue(SplitInstructionsView splitInstructionsView, float v) { splitInstructionsView.setScaleY(v); } @Override public Float get(SplitInstructionsView splitInstructionsView) { return splitInstructionsView.getScaleY(); } }; public static final FloatProperty<SplitInstructionsView> TEXT_ALPHA = new FloatProperty<SplitInstructionsView>("SplitInstructionsTextAlpha") { @Override public void setValue(SplitInstructionsView splitInstructionsView, float v) { splitInstructionsView.mTextView.setAlpha(v); } @Override public Float get(SplitInstructionsView splitInstructionsView) { return splitInstructionsView.mTextView.getAlpha(); } }; public SplitInstructionsView(Context context) { this(context, null); } Loading @@ -77,6 +105,9 @@ public class SplitInstructionsView extends FrameLayout { false ); splitInstructionsView.mTextView = splitInstructionsView.findViewById( R.id.split_instructions_text); dragLayer.addView(splitInstructionsView); return splitInstructionsView; } Loading Loading
quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java +3 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,9 @@ public class QuickstepAtomicAnimationFactory extends AllAppsSwipeController.applyAllAppsToNormalConfig(mActivity, config); } else if (fromState == NORMAL && toState == ALL_APPS) { AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mActivity, config); } else if (fromState == OVERVIEW && toState == OVERVIEW_SPLIT_SELECT) { config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, clampToProgress(LINEAR, 0, 0.167f)); } } }
quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java +9 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.launcher3.uioverrides.states; import android.content.Context; import com.android.launcher3.Launcher; import com.android.quickstep.views.RecentsView; Loading @@ -24,6 +26,8 @@ import com.android.quickstep.views.RecentsView; * pinned and user is selecting the second one */ public class SplitScreenSelectState extends OverviewState { private static final int OVERVIEW_SPLIT_SELECT_SLIDE_IN_DURATION = 500; public SplitScreenSelectState(int id) { super(id); } Loading @@ -38,4 +42,9 @@ public class SplitScreenSelectState extends OverviewState { RecentsView recentsView = launcher.getOverviewPanel(); return recentsView.getSplitSelectTranslation(); } @Override public int getTransitionDuration(Context context, boolean isToState) { return OVERVIEW_SPLIT_SELECT_SLIDE_IN_DURATION; } }
quickstep/src/com/android/quickstep/views/FloatingTaskView.java +18 −8 Original line number Diff line number Diff line Loading @@ -2,8 +2,9 @@ package com.android.quickstep.views; 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_3; import static com.android.launcher3.anim.Interpolators.FASTER_OUT_SLOWER_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.clampToProgress; import android.animation.ValueAnimator; import android.content.Context; Loading Loading @@ -200,10 +201,16 @@ public class FloatingTaskView extends FrameLayout { RectF floatingTaskViewBounds = new RectF(); if (fadeWithThumbnail) { animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ALPHA_FLOAT, 0, 1, ACCEL); // FloatingTaskThumbnailView: thumbnail fades out to transparent animation.addFloat(mThumbnailView, LauncherAnimUtils.VIEW_ALPHA, 1, 0, DEACCEL_3); 1, 0, clampToProgress(LINEAR, 0, 0.267f)); // SplitPlaceholderView: gray background fades in at the same time, then new icon fades // in animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ALPHA_FLOAT, 0, 1, clampToProgress(LINEAR, 0, 0.267f)); animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ICON_ALPHA, 0, 1, clampToProgress(LINEAR, 0.333f, 0.5f)); } else if (isStagedTask) { // Fade in the placeholder view when split is initiated from homescreen / all apps // icons. Loading @@ -214,12 +221,15 @@ public class FloatingTaskView extends FrameLayout { } MultiValueUpdateListener listener = new MultiValueUpdateListener() { final FloatProp mDx = new FloatProp(0, prop.dX, 0, animDuration, LINEAR); final FloatProp mDy = new FloatProp(0, prop.dY, 0, animDuration, LINEAR); // SplitPlaceholderView: rectangle translates and stretches to new position final FloatProp mDx = new FloatProp(0, prop.dX, 0, animDuration, clampToProgress(FASTER_OUT_SLOWER_IN, 0, 0.833f)); final FloatProp mDy = new FloatProp(0, prop.dY, 0, animDuration, clampToProgress(FASTER_OUT_SLOWER_IN, 0, 0.833f)); final FloatProp mTaskViewScaleX = new FloatProp(1f, prop.finalTaskViewScaleX, 0, animDuration, LINEAR); animDuration, clampToProgress(FASTER_OUT_SLOWER_IN, 0, 0.833f)); final FloatProp mTaskViewScaleY = new FloatProp(1f, prop.finalTaskViewScaleY, 0, animDuration, LINEAR); animDuration, clampToProgress(FASTER_OUT_SLOWER_IN, 0, 0.833f)); @Override public void onUpdate(float percent, boolean initOnly) { // Calculate the icon position. Loading
quickstep/src/com/android/quickstep/views/RecentsView.java +77 −15 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.ACCEL_0_75; import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL_2; import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE; 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; Loading Loading @@ -113,6 +114,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.UiThread; import androidx.core.graphics.ColorUtils; import androidx.dynamicanimation.animation.SpringForce; import com.android.launcher3.BaseActivity; import com.android.launcher3.BaseActivity.MultiWindowModeChangedListener; Loading @@ -125,6 +127,7 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.anim.SpringAnimationBuilder; import com.android.launcher3.anim.SpringProperty; import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.config.FeatureFlags; Loading Loading @@ -442,6 +445,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T private static final float ANIMATION_DISMISS_PROGRESS_MIDPOINT = 0.5f; private static final float END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.75f; private static final float INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.133f; private static final float ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.033f; private static final float SIGNIFICANT_MOVE_SCREEN_WIDTH_PERCENTAGE = 0.15f; protected final RecentsOrientedState mOrientationState; Loading Loading @@ -2825,7 +2831,20 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T RectF startingTaskRect = new RectF(); if (mSplitHiddenTaskView != null) { mSplitHiddenTaskView.setVisibility(INVISIBLE); // Split staging is initiated, hide the original TaskView except for the icon (which // needs to animate out over time) // If needed, visibility should be toggled back on in resetFromSplitSelectionState(). for (int i = 0; i < mSplitHiddenTaskView.getChildCount(); i++) { View child = mSplitHiddenTaskView.getChildAt(i); if (child != mSplitHiddenTaskView.mIconView) { child.setVisibility(INVISIBLE); } } // Icon animates out over time anim.addFloat(mSplitHiddenTaskView, TaskView.ICON_ALPHA, 1, 0, clampToProgress(LINEAR, 0, 0.167f)); mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity, mSplitHiddenTaskView.getThumbnail(), mSplitHiddenTaskView.getThumbnail().getThumbnail(), Loading @@ -2842,9 +2861,15 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T false /* fadeWithThumbnail */, true /* isStagedTask */); } // SplitInstructionsView: animate in mSplitInstructionsView = SplitInstructionsView.getSplitInstructionsView(mActivity); mSplitInstructionsView.setAlpha(0); anim.addFloat(mSplitInstructionsView, SplitInstructionsView.ALPHA_FLOAT, 0, 1, ACCEL); anim.addFloat(mSplitInstructionsView, SplitInstructionsView.CONTAINER_ALPHA, 0, 1, clampToProgress(LINEAR, 0, 0.167f)); anim.addFloat(mSplitInstructionsView, SplitInstructionsView.TEXT_ALPHA, 0, 1, clampToProgress(LINEAR, 0.1f, 0.267f)); anim.addFloat(mSplitInstructionsView, mSplitInstructionsView.UNFOLD, 0.1f, 1, clampToProgress(EMPHASIZED_DECELERATE, 0, 0.667f)); InteractionJankMonitorWrapper.begin(this, InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "First tile selected"); Loading Loading @@ -3124,11 +3149,22 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T // Animate task with index >= dismissed index and in the same row as the // dismissed index or next focused index. Offset successive task dismissal // durations for a staggered effect. float animationStartProgress = Utilities.boundToRange( distanceFromDismissedTask++; // If user is initiating splitscreen from the focused (large) task, we use a // spring-based animation and timings. For other, smaller, repositions, we currently // fall back on a less complicated linear animation and timings. float animationStartProgress = isFocusedTaskDismissed && nextFocusedTaskView == null ? Utilities.boundToRange( INITIAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + ADDITIONAL_SPRING_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * (int) Math.ceil(distanceFromDismissedTask / 2f), 0f, dismissTranslationInterpolationEnd) : Utilities.boundToRange( INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * ++distanceFromDismissedTask, 0f, * distanceFromDismissedTask, 0f, dismissTranslationInterpolationEnd); if (taskView == nextFocusedTaskView) { // Enlarge the task to be focused next, and translate into focus position. float scale = mTaskWidth / (float) mLastComputedGridTaskSize.width(); Loading Loading @@ -3163,8 +3199,31 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T primaryTranslation += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize; } } // Transitioning to split select -- set up staggered spring animation for // other TaskViews. Animator taskSlideIn = new SpringAnimationBuilder(taskView.mActivity) .setDampingRatio(0.85f) .setStiffness(SpringForce.STIFFNESS_LOW) .setEndValue(mIsRtl ? primaryTranslation : -primaryTranslation) .setStartValue( taskView.getPrimaryDismissTranslationProperty() .get(taskView) ) .build(taskView, taskView.getPrimaryDismissTranslationProperty()); long taskSlideInDuration = taskSlideIn.getDuration(); anim.add(taskSlideIn); taskSlideIn .setDuration(taskSlideInDuration) .setStartDelay( Math.round(animationStartProgress * anim.getDuration())); } else { // Task was dismissed individually -- translate other TaskViews to fill the // vacant space. // TODO (b/242075836): This dismiss animation uses a linear transition. // When the above bug is fixed, it can use the same (nicer) spring // transition as the focused task split case above. anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? primaryTranslation : -primaryTranslation, clampToProgress(LINEAR, animationStartProgress, Loading @@ -3172,6 +3231,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T } } } } if (needsCurveUpdates) { anim.addOnFrameCallback(this::updateCurveProperties); Loading @@ -3189,7 +3249,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T final boolean finalCloseGapBetweenClearAll = closeGapBetweenClearAll; final boolean finalSnapToLastTask = snapToLastTask; final boolean finalIsFocusedTaskDismissed = isFocusedTaskDismissed; mPendingAnimation.addEndListener(new Consumer<Boolean>() { Consumer endConsumer = new Consumer<Boolean>() { @Override public void accept(Boolean success) { if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile Loading Loading @@ -3399,7 +3460,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T onDismissAnimationEnds(); mPendingAnimation = null; } }); }; mPendingAnimation.addListener(AnimatorListeners.forEndCallback(endConsumer)); return anim; } Loading Loading @@ -4220,7 +4283,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T resetTaskVisuals(); mSplitHiddenTaskViewIndex = -1; if (mSplitHiddenTaskView != null) { mSplitHiddenTaskView.setVisibility(VISIBLE); mSplitHiddenTaskView = null; } } Loading
quickstep/src/com/android/quickstep/views/SplitInstructionsView.java +33 −2 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatTextView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; Loading @@ -40,9 +41,10 @@ import com.android.launcher3.util.DisplayController; */ public class SplitInstructionsView extends FrameLayout { private final StatefulActivity mLauncher; private AppCompatTextView mTextView; public static final FloatProperty<SplitInstructionsView> ALPHA_FLOAT = new FloatProperty<SplitInstructionsView>("SplitInstructionsAlpha") { public static final FloatProperty<SplitInstructionsView> CONTAINER_ALPHA = new FloatProperty<SplitInstructionsView>("SplitInstructionsContainerAlpha") { @Override public void setValue(SplitInstructionsView splitInstructionsView, float v) { splitInstructionsView.setVisibility(v != 0 ? VISIBLE : GONE); Loading @@ -55,6 +57,32 @@ public class SplitInstructionsView extends FrameLayout { } }; public static final FloatProperty<SplitInstructionsView> UNFOLD = new FloatProperty<SplitInstructionsView>("SplitInstructionsUnfold") { @Override public void setValue(SplitInstructionsView splitInstructionsView, float v) { splitInstructionsView.setScaleY(v); } @Override public Float get(SplitInstructionsView splitInstructionsView) { return splitInstructionsView.getScaleY(); } }; public static final FloatProperty<SplitInstructionsView> TEXT_ALPHA = new FloatProperty<SplitInstructionsView>("SplitInstructionsTextAlpha") { @Override public void setValue(SplitInstructionsView splitInstructionsView, float v) { splitInstructionsView.mTextView.setAlpha(v); } @Override public Float get(SplitInstructionsView splitInstructionsView) { return splitInstructionsView.mTextView.getAlpha(); } }; public SplitInstructionsView(Context context) { this(context, null); } Loading @@ -77,6 +105,9 @@ public class SplitInstructionsView extends FrameLayout { false ); splitInstructionsView.mTextView = splitInstructionsView.findViewById( R.id.split_instructions_text); dragLayer.addView(splitInstructionsView); return splitInstructionsView; } Loading