diff --git a/packages/SystemUI/res/layout/recents_incompatible_app_overlay.xml b/packages/SystemUI/res/layout/recents_incompatible_app_overlay.xml index 2b49dd33fd269..d2daa89ff03ba 100644 --- a/packages/SystemUI/res/layout/recents_incompatible_app_overlay.xml +++ b/packages/SystemUI/res/layout/recents_incompatible_app_overlay.xml @@ -26,5 +26,6 @@ android:layout_gravity="center" android:drawableTop="@drawable/recents_info_light" android:drawablePadding="8dp" - android:text="@string/recents_incompatible_app_message" /> + android:text="@string/recents_incompatible_app_message" + android:textColor="@android:color/white" /> \ No newline at end of file diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index ef84c76c4c5c9..e98309ebffb9a 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -144,12 +144,6 @@ 400 - - 175 - - - 300 - 200 diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 6876f31ce79cb..54713d072fc74 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -26,6 +26,7 @@ import android.content.IntentFilter; import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; +import android.os.Handler; import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; @@ -97,6 +98,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD public final static int INCOMPATIBLE_APP_ALPHA_DURATION = 150; private RecentsPackageMonitor mPackageMonitor; + private Handler mHandler = new Handler(); private long mLastTabKeyEventTime; private int mLastDeviceOrientation = Configuration.ORIENTATION_UNDEFINED; private int mLastDisplayDensity; @@ -138,12 +140,14 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD @Override public void run() { try { - ActivityOptions opts = mOpts; - if (opts == null) { - opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this, - R.anim.recents_to_launcher_enter, R.anim.recents_to_launcher_exit); - } - startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT); + mHandler.post(() -> { + ActivityOptions opts = mOpts; + if (opts == null) { + opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this, + R.anim.recents_to_launcher_enter, R.anim.recents_to_launcher_exit); + } + startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT); + }); } catch (Exception e) { Log.e(TAG, getString(R.string.recents_launch_error_message, "Home"), e); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java index 32b7a99e3084a..f42eea335e6f6 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java @@ -49,6 +49,7 @@ import android.util.SparseArray; import android.view.animation.Interpolator; import com.android.internal.policy.DockedDividerUtils; +import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsDebugFlags; @@ -253,7 +254,7 @@ public class TaskStack { private static final int HORIZONTAL = 0; private static final int VERTICAL = 1; - private static final int DOCK_AREA_ALPHA = 192; + private static final int DOCK_AREA_ALPHA = 80; public static final DockState NONE = new DockState(DOCKED_INVALID, -1, 80, 255, HORIZONTAL, null, null, null); public static final DockState LEFT = new DockState(DOCKED_LEFT, @@ -368,19 +369,28 @@ public class TaskStack { mDockAreaOverlayAnimator.cancel(); } + ObjectAnimator anim; ArrayList animators = new ArrayList<>(); if (dockAreaOverlay.getAlpha() != areaAlpha) { if (animateAlpha) { - animators.add(ObjectAnimator.ofInt(dockAreaOverlay, - Utilities.DRAWABLE_ALPHA, dockAreaOverlay.getAlpha(), areaAlpha)); + anim = ObjectAnimator.ofInt(dockAreaOverlay, + Utilities.DRAWABLE_ALPHA, dockAreaOverlay.getAlpha(), areaAlpha); + anim.setDuration(duration); + anim.setInterpolator(interpolator); + animators.add(anim); } else { dockAreaOverlay.setAlpha(areaAlpha); } } if (mHintTextAlpha != hintAlpha) { if (animateAlpha) { - animators.add(ObjectAnimator.ofInt(this, HINT_ALPHA, mHintTextAlpha, - hintAlpha)); + anim = ObjectAnimator.ofInt(this, HINT_ALPHA, mHintTextAlpha, + hintAlpha); + anim.setDuration(150); + anim.setInterpolator(hintAlpha > mHintTextAlpha + ? Interpolators.ALPHA_IN + : Interpolators.ALPHA_OUT); + animators.add(anim); } else { mHintTextAlpha = hintAlpha; dockAreaOverlay.invalidateSelf(); @@ -390,8 +400,11 @@ public class TaskStack { if (animateBounds) { PropertyValuesHolder prop = PropertyValuesHolder.ofObject( Utilities.DRAWABLE_RECT, Utilities.RECT_EVALUATOR, - dockAreaOverlay.getBounds(), bounds); - animators.add(ObjectAnimator.ofPropertyValuesHolder(dockAreaOverlay, prop)); + new Rect(dockAreaOverlay.getBounds()), bounds); + anim = ObjectAnimator.ofPropertyValuesHolder(dockAreaOverlay, prop); + anim.setDuration(duration); + anim.setInterpolator(interpolator); + animators.add(anim); } else { dockAreaOverlay.setBounds(bounds); } @@ -399,8 +412,6 @@ public class TaskStack { if (!animators.isEmpty()) { mDockAreaOverlayAnimator = new AnimatorSet(); mDockAreaOverlayAnimator.playTogether(animators); - mDockAreaOverlayAnimator.setDuration(duration); - mDockAreaOverlayAnimator.setInterpolator(interpolator); mDockAreaOverlayAnimator.start(); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java index 48e137028a7fc..5e87e2a75c80c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java @@ -18,6 +18,7 @@ package com.android.systemui.recents.views; import android.animation.Animator; import android.animation.AnimatorSet; +import android.animation.ValueAnimator; import android.annotation.IntDef; import android.util.SparseArray; import android.util.SparseLongArray; @@ -53,6 +54,7 @@ public class AnimationProps { public static final int FOCUS_STATE = 8; private SparseLongArray mPropStartDelay; + private SparseLongArray mPropInitialPlayTime; private SparseLongArray mPropDuration; private SparseArray mPropInterpolators; private Animator.AnimatorListener mListener; @@ -116,10 +118,14 @@ public class AnimationProps { * Applies the specific start delay, duration and interpolator to the given {@param animator} * for the specified {@param propertyType}. */ - public T apply(@PropType int propertyType, T animator) { + public T apply(@PropType int propertyType, T animator) { animator.setStartDelay(getStartDelay(propertyType)); animator.setDuration(getDuration(propertyType)); animator.setInterpolator(getInterpolator(propertyType)); + long initialPlayTime = getInitialPlayTime(propertyType); + if (initialPlayTime != 0) { + animator.setCurrentPlayTime(initialPlayTime); + } return animator; } @@ -134,6 +140,17 @@ public class AnimationProps { return this; } + /** + * Sets a initial play time for a specific property. + */ + public AnimationProps setInitialPlayTime(@PropType int propertyType, int initialPlayTime) { + if (mPropInitialPlayTime == null) { + mPropInitialPlayTime = new SparseLongArray(); + } + mPropInitialPlayTime.append(propertyType, initialPlayTime); + return this; + } + /** * Returns the start delay for a specific property. */ @@ -199,6 +216,20 @@ public class AnimationProps { return Interpolators.LINEAR; } + /** + * Returns the initial play time for a specific property, falling back to the general initial + * play time if there is no specific property interpolator. + */ + public long getInitialPlayTime(@PropType int propertyType) { + if (mPropInitialPlayTime != null) { + if (mPropInitialPlayTime.indexOfKey(propertyType) != -1) { + return mPropInitialPlayTime.get(propertyType); + } + return mPropInitialPlayTime.get(ALL, 0); + } + return 0; + } + /** * Sets an animator listener for this animation. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 6ecd52dbccc50..fd27b4f1fc278 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -88,7 +88,6 @@ public class RecentsView extends FrameLayout { private static final String TAG = "RecentsView"; - private static final int DOCK_AREA_OVERLAY_TRANSITION_DURATION = 135; private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200; private static final float DEFAULT_SCRIM_ALPHA = 0.33f; @@ -733,8 +732,8 @@ public class RecentsView extends FrameLayout { TaskStack.DockState.ViewState viewState = dockState.viewState; if (newDockStates == null || !newDockStatesSet.contains(dockState)) { // This is no longer visible, so hide it - viewState.startAnimation(null, 0, 0, DOCK_AREA_OVERLAY_TRANSITION_DURATION, - Interpolators.ALPHA_OUT, animateAlpha, animateBounds); + viewState.startAnimation(null, 0, 0, TaskStackView.SLOW_SYNC_STACK_DURATION, + Interpolators.FAST_OUT_SLOW_IN, animateAlpha, animateBounds); } else { // This state is now visible, update the bounds and show it int areaAlpha = overrideAreaAlpha != -1 @@ -752,7 +751,7 @@ public class RecentsView extends FrameLayout { viewState.dockAreaOverlay.setBounds(bounds); } viewState.startAnimation(bounds, areaAlpha, hintAlpha, - DOCK_AREA_OVERLAY_TRANSITION_DURATION, Interpolators.ALPHA_IN, + TaskStackView.SLOW_SYNC_STACK_DURATION, Interpolators.FAST_OUT_SLOW_IN, animateAlpha, animateBounds); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java index e79306f55e3dc..b422cca25a82c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java @@ -18,6 +18,7 @@ package com.android.systemui.recents.views; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.TimeInterpolator; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; @@ -32,7 +33,6 @@ import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsActivityLaunchState; import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.misc.ReferenceCountedTrigger; -import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; @@ -74,32 +74,35 @@ public class TaskStackAnimationHelper { void onStartFrontTaskEnterAnimation(boolean screenPinningEnabled); } + private static final int DOUBLE_FRAME_OFFSET_MS = 33; private static final int FRAME_OFFSET_MS = 16; - public static final int ENTER_FROM_HOME_ALPHA_DURATION = 100; - public static final int ENTER_FROM_HOME_TRANSLATION_DURATION = 333; + private static final int ENTER_EXIT_NUM_ANIMATING_TASKS = 5; - private static final PathInterpolator ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR = - new PathInterpolator(0, 0, 0, 1f); - private static final PathInterpolator ENTER_FROM_HOME_ALPHA_INTERPOLATOR = - new PathInterpolator(0, 0, 0.2f, 1f); + private static final int ENTER_FROM_HOME_ALPHA_DURATION = 100; + public static final int ENTER_FROM_HOME_TRANSLATION_DURATION = 300; + private static final Interpolator ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR = + Interpolators.LINEAR_OUT_SLOW_IN; + private static final Interpolator ENTER_FROM_HOME_ALPHA_INTERPOLATOR = Interpolators.LINEAR; - public static final int EXIT_TO_HOME_ALPHA_DURATION = 100; - public static final int EXIT_TO_HOME_TRANSLATION_DURATION = 150; - private static final PathInterpolator EXIT_TO_HOME_TRANSLATION_INTERPOLATOR = - new PathInterpolator(0.8f, 0, 0.6f, 1f); - private static final PathInterpolator EXIT_TO_HOME_ALPHA_INTERPOLATOR = + public static final int EXIT_TO_HOME_TRANSLATION_DURATION = 200; + private static final Interpolator EXIT_TO_HOME_TRANSLATION_INTERPOLATOR = + new PathInterpolator(0.4f, 0, 0.6f, 1f); + + private static final int DISMISS_TASK_DURATION = 175; + private static final int DISMISS_ALL_TASKS_DURATION = 200; + private static final Interpolator DISMISS_ALL_TRANSLATION_INTERPOLATOR = new PathInterpolator(0.4f, 0, 1f, 1f); - private static final PathInterpolator FOCUS_NEXT_TASK_INTERPOLATOR = + private static final Interpolator FOCUS_NEXT_TASK_INTERPOLATOR = new PathInterpolator(0.4f, 0, 0, 1f); - private static final PathInterpolator FOCUS_IN_FRONT_NEXT_TASK_INTERPOLATOR = + private static final Interpolator FOCUS_IN_FRONT_NEXT_TASK_INTERPOLATOR = new PathInterpolator(0, 0, 0, 1f); - private static final PathInterpolator FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR = - new PathInterpolator(0.4f, 0, 0.2f, 1f); + private static final Interpolator FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR = + Interpolators.LINEAR_OUT_SLOW_IN; - private static final PathInterpolator ENTER_WHILE_DOCKING_INTERPOLATOR = - new PathInterpolator(0, 0, 0.2f, 1f); + private static final Interpolator ENTER_WHILE_DOCKING_INTERPOLATOR = + Interpolators.LINEAR_OUT_SLOW_IN; private TaskStackView mStackView; @@ -251,16 +254,20 @@ public class TaskStackAnimationHelper { } } else if (launchState.launchedFromHome) { - // Animate the tasks up + // Animate the tasks up, but offset the animations to be relative to the front-most + // task animation AnimationProps taskAnimation = new AnimationProps() - .setStartDelay(AnimationProps.ALPHA, taskIndexFromFront * FRAME_OFFSET_MS) + .setInitialPlayTime(AnimationProps.BOUNDS, + Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS, taskIndexFromFront) * + DOUBLE_FRAME_OFFSET_MS) + .setStartDelay(AnimationProps.ALPHA, + Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS, taskIndexFromFront) * + FRAME_OFFSET_MS) + .setDuration(AnimationProps.BOUNDS, ENTER_FROM_HOME_TRANSLATION_DURATION) .setDuration(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_DURATION) - .setDuration(AnimationProps.BOUNDS, ENTER_FROM_HOME_TRANSLATION_DURATION - - (taskIndexFromFront * FRAME_OFFSET_MS)) .setInterpolator(AnimationProps.BOUNDS, ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR) - .setInterpolator(AnimationProps.ALPHA, - ENTER_FROM_HOME_ALPHA_INTERPOLATOR) + .setInterpolator(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_INTERPOLATOR) .setListener(postAnimationTrigger.decrementOnAnimationEnd()); postAnimationTrigger.increment(); mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation); @@ -270,8 +277,8 @@ public class TaskStackAnimationHelper { } else if (launchState.launchedViaDockGesture) { // Animate the tasks up AnimationProps taskAnimation = new AnimationProps() - .setDuration(AnimationProps.BOUNDS, (int) (dockGestureAnimDuration + - (taskIndexFromBack * 2f * FRAME_OFFSET_MS))) + .setDuration(AnimationProps.BOUNDS, dockGestureAnimDuration + + (taskIndexFromBack * DOUBLE_FRAME_OFFSET_MS)) .setInterpolator(AnimationProps.BOUNDS, ENTER_WHILE_DOCKING_INTERPOLATOR) .setListener(postAnimationTrigger.decrementOnAnimationEnd()); @@ -302,20 +309,17 @@ public class TaskStackAnimationHelper { for (int i = 0; i < taskViewCount; i++) { int taskIndexFromFront = taskViewCount - i - 1; TaskView tv = taskViews.get(i); - Task task = tv.getTask(); // Animate the tasks down AnimationProps taskAnimation; if (animated) { + int delay = Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS , taskIndexFromFront) * + DOUBLE_FRAME_OFFSET_MS; taskAnimation = new AnimationProps() - .setStartDelay(AnimationProps.ALPHA, i * FRAME_OFFSET_MS) - .setDuration(AnimationProps.ALPHA, EXIT_TO_HOME_ALPHA_DURATION) - .setDuration(AnimationProps.BOUNDS, EXIT_TO_HOME_TRANSLATION_DURATION + - (taskIndexFromFront * FRAME_OFFSET_MS)) + .setStartDelay(AnimationProps.BOUNDS, delay) + .setDuration(AnimationProps.BOUNDS, EXIT_TO_HOME_TRANSLATION_DURATION) .setInterpolator(AnimationProps.BOUNDS, EXIT_TO_HOME_TRANSLATION_INTERPOLATOR) - .setInterpolator(AnimationProps.ALPHA, - EXIT_TO_HOME_ALPHA_INTERPOLATOR) .setListener(postAnimationTrigger.decrementOnAnimationEnd()); postAnimationTrigger.increment(); } else { @@ -323,7 +327,6 @@ public class TaskStackAnimationHelper { } mTmpTransform.fillIn(tv); - mTmpTransform.alpha = 0f; mTmpTransform.rect.offset(0, offscreenYOffset); mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation); } @@ -384,8 +387,6 @@ public class TaskStackAnimationHelper { Resources res = mStackView.getResources(); TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm(); - int taskViewRemoveAnimDuration = res.getInteger( - R.integer.recents_animate_task_view_remove_duration); int offscreenXOffset = mStackView.getMeasuredWidth() - stackLayout.mTaskRect.left; // Disabling clipping with the stack while the view is animating away, this will get @@ -393,7 +394,7 @@ public class TaskStackAnimationHelper { deleteTaskView.setClipViewInStack(false); // Compose the new animation and transform and star the animation - AnimationProps taskAnimation = new AnimationProps(taskViewRemoveAnimDuration, + AnimationProps taskAnimation = new AnimationProps(DISMISS_TASK_DURATION, Interpolators.ALPHA_OUT, new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -413,29 +414,23 @@ public class TaskStackAnimationHelper { */ public void startDeleteAllTasksAnimation(final List taskViews, final ReferenceCountedTrigger postAnimationTrigger) { - Resources res = mStackView.getResources(); TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm(); - int taskViewRemoveAnimDuration = res.getInteger( - R.integer.recents_animate_task_views_remove_all_duration); int offscreenXOffset = mStackView.getMeasuredWidth() - stackLayout.mTaskRect.left; int taskViewCount = taskViews.size(); - int startDelayMax = 125; for (int i = taskViewCount - 1; i >= 0; i--) { TaskView tv = taskViews.get(i); - int indexFromFront = taskViewCount - i - 1; - float x = Interpolators.ACCELERATE.getInterpolation((float) indexFromFront / - taskViewCount); - int startDelay = (int) Utilities.mapRange(x, 0, startDelayMax); + int taskIndexFromFront = taskViewCount - i - 1; + int startDelay = taskIndexFromFront * DOUBLE_FRAME_OFFSET_MS; // Disabling clipping with the stack while the view is animating away tv.setClipViewInStack(false); // Compose the new animation and transform and star the animation AnimationProps taskAnimation = new AnimationProps(startDelay, - taskViewRemoveAnimDuration, Interpolators.FAST_OUT_LINEAR_IN, + DISMISS_ALL_TASKS_DURATION, DISMISS_ALL_TRANSLATION_INTERPOLATOR, new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -605,7 +600,7 @@ public class TaskStackAnimationHelper { // Now, animate in the front-most task if (frontMostTaskView != null) { mStackView.updateTaskViewToTransform(frontMostTaskView, frontMostTransform, - new AnimationProps(75, 200, FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR)); + new AnimationProps(75, 250, FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR)); } } }); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index e1e863c20f9c2..48f9453e15fd0 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -110,6 +110,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal private static final float HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD = 0.3f; public static final int DEFAULT_SYNC_STACK_DURATION = 200; + public static final int SLOW_SYNC_STACK_DURATION = 250; private static final int DRAG_SCALE_DURATION = 175; static final float DRAG_SCALE_FACTOR = 1.05f; @@ -1797,7 +1798,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } public final void onBusEvent(DragDropTargetChangedEvent event) { - AnimationProps animation = new AnimationProps(250, Interpolators.FAST_OUT_SLOW_IN); + AnimationProps animation = new AnimationProps(SLOW_SYNC_STACK_DURATION, + Interpolators.FAST_OUT_SLOW_IN); boolean ignoreTaskOverrides = false; if (event.dropTarget instanceof TaskStack.DockState) { // Calculate the new task stack bounds that matches the window size that Recents will