diff --git a/go/quickstep/src/com/android/quickstep/TaskActionController.java b/go/quickstep/src/com/android/quickstep/TaskActionController.java index b2d495bcb8..77b287ba5d 100644 --- a/go/quickstep/src/com/android/quickstep/TaskActionController.java +++ b/go/quickstep/src/com/android/quickstep/TaskActionController.java @@ -71,7 +71,6 @@ public final class TaskActionController { * Clears all tasks and updates the model and view. */ public void clearAllTasks() { - // TODO: Play an animation so transition is more natural. int count = mAdapter.getItemCount(); ActivityManagerWrapper.getInstance().removeAllRecentTasks(); mLoader.clearAllTasks(); diff --git a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java index a1d62c2bb4..1e017255fc 100644 --- a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java +++ b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java @@ -19,6 +19,10 @@ import static androidx.recyclerview.widget.LinearLayoutManager.VERTICAL; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; +import android.animation.ValueAnimator; import android.content.Context; import android.util.AttributeSet; import android.util.FloatProperty; @@ -65,6 +69,10 @@ public final class IconRecentsView extends FrameLayout { } }; private static final long CROSSFADE_DURATION = 300; + private static final long ITEM_ANIMATE_OUT_DURATION = 150; + private static final long ITEM_ANIMATE_OUT_DELAY_BETWEEN = 40; + private static final float ITEM_ANIMATE_OUT_TRANSLATION_X_RATIO = .25f; + private static final long CLEAR_ALL_FADE_DELAY = 120; /** * A ratio representing the view's relative placement within its padded space. For example, 0 @@ -119,7 +127,7 @@ public final class IconRecentsView extends FrameLayout { }); View clearAllView = findViewById(R.id.clear_all_button); - clearAllView.setOnClickListener(v -> mTaskActionController.clearAllTasks()); + clearAllView.setOnClickListener(v -> animateClearAllTasks()); } } @@ -194,6 +202,76 @@ public final class IconRecentsView extends FrameLayout { return view.getThumbnailView(); } + /** + * Clear all tasks and animate out. + */ + private void animateClearAllTasks() { + TaskItemView[] itemViews = getTaskViews(); + + AnimatorSet clearAnim = new AnimatorSet(); + long currentDelay = 0; + + // Animate each item view to the right and fade out. + for (TaskItemView itemView : itemViews) { + PropertyValuesHolder transXproperty = PropertyValuesHolder.ofFloat(TRANSLATION_X, + 0, itemView.getWidth() * ITEM_ANIMATE_OUT_TRANSLATION_X_RATIO); + PropertyValuesHolder alphaProperty = PropertyValuesHolder.ofFloat(ALPHA, 1.0f, 0f); + ObjectAnimator itemAnim = ObjectAnimator.ofPropertyValuesHolder(itemView, + transXproperty, alphaProperty); + itemAnim.setDuration(ITEM_ANIMATE_OUT_DURATION); + itemAnim.setStartDelay(currentDelay); + + clearAnim.play(itemAnim); + currentDelay += ITEM_ANIMATE_OUT_DELAY_BETWEEN; + } + + // Animate view fading and leave recents when faded enough. + ValueAnimator contentAlpha = ValueAnimator.ofFloat(1.0f, 0f) + .setDuration(CROSSFADE_DURATION); + contentAlpha.setStartDelay(CLEAR_ALL_FADE_DELAY); + contentAlpha.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + private boolean mLeftRecents = false; + + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + mContentView.setAlpha((float) valueAnimator.getAnimatedValue()); + // Leave recents while fading out. + if ((float) valueAnimator.getAnimatedValue() < .5f && !mLeftRecents) { + mActivityHelper.leaveRecents(); + mLeftRecents = true; + } + } + }); + + clearAnim.play(contentAlpha); + clearAnim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + for (TaskItemView itemView : itemViews) { + itemView.setTranslationX(0); + itemView.setAlpha(1.0f); + } + mContentView.setVisibility(GONE); + mTaskActionController.clearAllTasks(); + } + }); + clearAnim.start(); + } + + /** + * Get attached task item views ordered by most recent. + * + * @return array of attached task item views + */ + private TaskItemView[] getTaskViews() { + int taskCount = mTaskRecyclerView.getChildCount(); + TaskItemView[] itemViews = new TaskItemView[taskCount]; + for (int i = 0; i < taskCount; i ++) { + itemViews[i] = (TaskItemView) mTaskRecyclerView.getChildAt(i); + } + return itemViews; + } + /** * Update the content view so that the appropriate view is shown based off the current list * of tasks.