summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI/src/com/android/systemui
diff options
context:
space:
mode:
Diffstat (limited to 'packages/SystemUI/src/com/android/systemui')
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java67
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Constants.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Utilities.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java204
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java17
7 files changed, 261 insertions, 81 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java b/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java
new file mode 100644
index 0000000..b085211
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java
@@ -0,0 +1,67 @@
+package com.android.systemui.recents;
+
+import android.animation.TimeInterpolator;
+
+/**
+ * A pre-baked bezier-curved interpolator for quantum-paper transitions.
+ */
+public class BakedBezierInterpolator implements TimeInterpolator {
+ public static final BakedBezierInterpolator INSTANCE = new BakedBezierInterpolator();
+
+ /**
+ * Use the INSTANCE variable instead of instantiating.
+ */
+ private BakedBezierInterpolator() {
+ super();
+ }
+
+ /**
+ * Lookup table values.
+ * Generated using a Bezier curve from (0,0) to (1,1) with control points:
+ * P0 (0,0)
+ * P1 (0.4, 0)
+ * P2 (0.2, 1.0)
+ * P3 (1.0, 1.0)
+ *
+ * Values sampled with x at regular intervals between 0 and 1.
+ *
+ * These values were generated using:
+ * ./scripts/bezier_interpolator_values_gen.py 0.4 0.2
+ */
+ private static final float[] VALUES = new float[] {
+ 0.0f, 0.0002f, 0.0009f, 0.0019f, 0.0036f, 0.0059f, 0.0086f, 0.0119f, 0.0157f, 0.0209f,
+ 0.0257f, 0.0321f, 0.0392f, 0.0469f, 0.0566f, 0.0656f, 0.0768f, 0.0887f, 0.1033f, 0.1186f,
+ 0.1349f, 0.1519f, 0.1696f, 0.1928f, 0.2121f, 0.237f, 0.2627f, 0.2892f, 0.3109f, 0.3386f,
+ 0.3667f, 0.3952f, 0.4241f, 0.4474f, 0.4766f, 0.5f, 0.5234f, 0.5468f, 0.5701f, 0.5933f,
+ 0.6134f, 0.6333f, 0.6531f, 0.6698f, 0.6891f, 0.7054f, 0.7214f, 0.7346f, 0.7502f, 0.763f,
+ 0.7756f, 0.7879f, 0.8f, 0.8107f, 0.8212f, 0.8326f, 0.8415f, 0.8503f, 0.8588f, 0.8672f,
+ 0.8754f, 0.8833f, 0.8911f, 0.8977f, 0.9041f, 0.9113f, 0.9165f, 0.9232f, 0.9281f, 0.9328f,
+ 0.9382f, 0.9434f, 0.9476f, 0.9518f, 0.9557f, 0.9596f, 0.9632f, 0.9662f, 0.9695f, 0.9722f,
+ 0.9753f, 0.9777f, 0.9805f, 0.9826f, 0.9847f, 0.9866f, 0.9884f, 0.9901f, 0.9917f, 0.9931f,
+ 0.9944f, 0.9955f, 0.9964f, 0.9973f, 0.9981f, 0.9986f, 0.9992f, 0.9995f, 0.9998f, 1.0f, 1.0f
+ };
+
+ private static final float STEP_SIZE = 1.0f / (VALUES.length - 1);
+
+ @Override
+ public float getInterpolation(float input) {
+ if (input >= 1.0f) {
+ return 1.0f;
+ }
+
+ if (input <= 0f) {
+ return 0f;
+ }
+
+ int position = Math.min(
+ (int)(input * (VALUES.length - 1)),
+ VALUES.length - 2);
+
+ float quantized = position * STEP_SIZE;
+ float difference = input - quantized;
+ float weight = difference / STEP_SIZE;
+
+ return VALUES[position] + weight * (VALUES[position + 1] - VALUES[position]);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 8c5c8fa..86f188e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -34,7 +34,7 @@ public class Constants {
// For debugging, this enables us to create mock recents tasks
public static final boolean EnableSystemServicesProxy = false;
// For debugging, this defines the number of mock recents packages to create
- public static final int SystemServicesProxyMockPackageCount = 12;
+ public static final int SystemServicesProxyMockPackageCount = 3;
// For debugging, this defines the number of mock recents tasks to create
public static final int SystemServicesProxyMockTaskCount = 75;
@@ -82,16 +82,8 @@ public class Constants {
}
public static class TaskStackView {
- public static class Animation {
- public static final int TaskRemovedReshuffleDuration = 200;
- public static final int SnapScrollBackDuration = 650;
- public static final int FilteredCurrentViewsDuration = 150;
- public static final int FilteredNewViewsDuration = 200;
- public static final int UnfilteredCurrentViewsDuration = 150;
- public static final int UnfilteredNewViewsDuration = 200;
- }
-
public static final int TaskStackOverscrollRange = 150;
+ public static final int FilterStartDelay = 25;
// The padding will be applied to the smallest dimension, and then applied to all sides
public static final float StackPaddingPct = 0.15f;
@@ -106,12 +98,6 @@ public class Constants {
}
public static class TaskView {
- public static class Animation {
- public static final int TaskDataUpdatedFadeDuration = 250;
- public static final int TaskIconOnEnterDuration = 175;
- public static final int TaskIconOnLeavingDuration = 75;
- }
-
public static final boolean AnimateFrontTaskIconOnEnterRecents = true;
public static final boolean AnimateFrontTaskIconOnLeavingRecents = true;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 3d47cb6..5d58a09 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -17,11 +17,11 @@
package com.android.systemui.recents;
import android.content.Context;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.TypedValue;
+import com.android.systemui.R;
/** A static Recents configuration for the current context
@@ -34,6 +34,11 @@ public class RecentsConfiguration {
public Rect systemInsets = new Rect();
public Rect displayRect = new Rect();
+ public float animationDpsMovementPerSecond;
+
+ public int filteringCurrentViewsMinAnimDuration;
+ public int filteringNewViewsMinAnimDuration;
+
/** Private constructor */
private RecentsConfiguration() {}
@@ -58,6 +63,12 @@ public class RecentsConfiguration {
mDisplayMetrics = dm;
displayRect.set(0, 0, dm.widthPixels, dm.heightPixels);
+ animationDpsMovementPerSecond =
+ res.getDimensionPixelSize(R.dimen.recents_animation_movement_in_dps_per_second);
+ filteringCurrentViewsMinAnimDuration =
+ res.getInteger(R.integer.recents_filter_animate_current_views_min_duration);
+ filteringNewViewsMinAnimDuration =
+ res.getInteger(R.integer.recents_filter_animate_new_views_min_duration);
}
public void updateSystemInsets(Rect insets) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index f147fbc..efcd948 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -51,9 +51,9 @@ public class SystemServicesProxy {
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
// Create a dummy icon
- mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8);
+ mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(mDummyIcon);
- c.drawColor(0xFFFF0000);
+ c.drawColor(0xFF999999);
c.setBitmap(null);
}
}
@@ -77,7 +77,7 @@ public class SystemServicesProxy {
rti.id = rti.persistentId = i;
rti.baseIntent = new Intent();
rti.baseIntent.setComponent(cn);
- rti.description = rti.activityLabel =
+ rti.description = rti.activityLabel = "" + i + " - " +
Long.toString(Math.abs(new Random().nextLong()), 36);
if (i % 2 == 0) {
rti.activityIcon = Bitmap.createBitmap(mDummyIcon);
@@ -118,7 +118,7 @@ public class SystemServicesProxy {
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
Bitmap thumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(thumbnail);
- c.drawColor(0xFF00ff00);
+ c.drawColor(0xff333333);
c.setBitmap(null);
return thumbnail;
}
@@ -178,7 +178,7 @@ public class SystemServicesProxy {
// If we are mocking, then return a mock label
if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
- return new ColorDrawable(0xFFff0000);
+ return new ColorDrawable(0xFF666666);
}
return info.loadIcon(mPm);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
index 9048cba..9538ad0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
@@ -20,6 +20,19 @@ import android.graphics.Rect;
/* Common code */
public class Utilities {
+ /**
+ * Calculates a consistent animation duration (ms) for all animations depending on the movement
+ * of the object being animated.
+ */
+ public static int calculateTranslationAnimationDuration(int distancePx) {
+ return calculateTranslationAnimationDuration(distancePx, 100);
+ }
+ public static int calculateTranslationAnimationDuration(int distancePx, int minDuration) {
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ return Math.max(minDuration,
+ (int) (Math.abs(distancePx) / config.animationDpsMovementPerSecond) * 1000 /* ms/s */);
+ }
+
/** Scales a rect about its centroid */
public static void scaleRectAboutCenter(Rect r, float scale) {
if (scale != 1.0f) {
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 dfd608c..fa06764 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -35,11 +35,11 @@ import android.view.ViewParent;
import android.widget.FrameLayout;
import android.widget.OverScroller;
import com.android.systemui.R;
+import com.android.systemui.recents.BakedBezierInterpolator;
import com.android.systemui.recents.Console;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsTaskLoader;
-import com.android.systemui.recents.SystemServicesProxy;
import com.android.systemui.recents.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
@@ -76,6 +76,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
OverScroller mScroller;
ObjectAnimator mScrollAnimator;
+ // Filtering
+ AnimatorSet mFilterChildrenAnimator;
+
// Optimizations
int mHwLayersRefCount;
int mStackViewsAnimationDuration;
@@ -180,7 +183,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
*/
private ArrayList<TaskViewTransform> getStackTransforms(ArrayList<Task> tasks,
int stackScroll,
- int[] visibleRangeOut) {
+ int[] visibleRangeOut,
+ boolean boundTranslationsToRect) {
// XXX: Optimization: Use binary search to find the visible range
ArrayList<TaskViewTransform> taskTransforms = new ArrayList<TaskViewTransform>();
@@ -196,6 +200,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
lastVisibleIndex = i;
}
+
+ if (boundTranslationsToRect) {
+ transform.translationY = Math.min(transform.translationY, mRect.bottom);
+ }
}
if (visibleRangeOut != null) {
visibleRangeOut[0] = firstVisibleIndex;
@@ -219,7 +227,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int stackScroll = getStackScroll();
ArrayList<Task> tasks = mStack.getTasks();
ArrayList<TaskViewTransform> taskTransforms = getStackTransforms(tasks, stackScroll,
- visibleRange);
+ visibleRange, false);
// Update the visible state of all the tasks
int taskCount = tasks.size();
@@ -286,7 +294,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
/** Animates the stack scroll into bounds */
- ObjectAnimator animateBoundScroll(int duration) {
+ ObjectAnimator animateBoundScroll() {
int curScroll = getStackScroll();
int newScroll = Math.max(mMinScroll, Math.min(mMaxScroll, curScroll));
if (newScroll != curScroll) {
@@ -298,16 +306,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
abortBoundScrollAnimation();
// Start a new scroll animation
- animateScroll(curScroll, newScroll, duration);
+ animateScroll(curScroll, newScroll);
mScrollAnimator.start();
}
return mScrollAnimator;
}
/** Animates the stack scroll */
- void animateScroll(int curScroll, int newScroll, int duration) {
+ void animateScroll(int curScroll, int newScroll) {
mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
- mScrollAnimator.setDuration(duration);
+ mScrollAnimator.setDuration(Utilities.calculateTranslationAnimationDuration(newScroll -
+ curScroll, 250));
+ mScrollAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
@@ -625,7 +635,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
updateMinMaxScroll(true);
- requestSynchronizeStackViewsWithModel(Constants.Values.TaskStackView.Animation.TaskRemovedReshuffleDuration);
+ int movement = (int) (Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height());
+ requestSynchronizeStackViewsWithModel(Utilities.calculateTranslationAnimationDuration(movement));
}
@Override
@@ -635,20 +646,22 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// (filtered) stack
// XXX: Use HW Layers
- // Stash the scroll for us to restore to when we unfilter
+ // Stash the scroll and filtered task for us to restore to when we unfilter
mStashedScroll = getStackScroll();
// Compute the transforms of the items in the current stack
final ArrayList<TaskViewTransform> curTaskTransforms =
- getStackTransforms(curStack, mStashedScroll, null);
+ getStackTransforms(curStack, mStashedScroll, null, true);
- // Bound the new stack scroll
+ // Scroll the item to the top of the stack (sans-peek) rect so that we can see it better
updateMinMaxScroll(false);
+ float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
+ setStackScrollRaw((int) (newStack.indexOfTask(filteredTask) * overlapHeight));
boundScrollRaw();
- // Compute the transforms of the items in the new stack
+ // Compute the transforms of the items in the new stack after setting the new scroll
final ArrayList<TaskViewTransform> taskTransforms =
- getStackTransforms(mStack.getTasks(), getStackScroll(), null);
+ getStackTransforms(mStack.getTasks(), getStackScroll(), null, true);
// Animate all of the existing views on screen either out of view (if they are not visible
// in the new stack) or to their final positions in the new stack
@@ -656,13 +669,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
final ArrayList<Task> tasks = mStack.getTasks();
ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
int childCount = getChildCount();
+ int movement = 0;
for (int i = 0; i < childCount; i++) {
TaskView tv = (TaskView) getChildAt(i);
Task task = tv.getTask();
TaskViewTransform toTransform;
int taskIndex = tasks.indexOf(task);
- if ((taskIndex < 0) || !taskTransforms.get(taskIndex).visible) {
- // Compose a new transform that animates the task view out of view
+
+ boolean willBeInvisible = (taskIndex < 0) || !taskTransforms.get(taskIndex).visible;
+ if (willBeInvisible) {
+ // Compose a new transform that fades and slides the task out of view
TaskViewTransform fromTransform = curTaskTransforms.get(curStack.indexOf(task));
toTransform = new TaskViewTransform(fromTransform);
tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
@@ -671,23 +687,49 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
childrenToReturnToPool.add(tv);
} else {
toTransform = taskTransforms.get(taskIndex);
+
+ // Use the movement of the visible views to calculate the duration of the animation
+ movement = Math.max(movement,
+ Math.abs(toTransform.translationY - (int) tv.getTranslationY()));
}
childViewAnims.add(tv.getAnimatorToTaskTransform(toTransform));
}
- AnimatorSet childViewAnimSet = new AnimatorSet();
- childViewAnimSet.setDuration(
- Constants.Values.TaskStackView.Animation.FilteredCurrentViewsDuration);
- childViewAnimSet.addListener(new AnimatorListenerAdapter() {
+ // Cancel the previous animation
+ if (mFilterChildrenAnimator != null) {
+ mFilterChildrenAnimator.cancel();
+ mFilterChildrenAnimator.removeAllListeners();
+ }
+
+ // Create a new animation for the existing children
+ final RecentsConfiguration config = RecentsConfiguration.getInstance();
+ mFilterChildrenAnimator = new AnimatorSet();
+ mFilterChildrenAnimator.setDuration(
+ Utilities.calculateTranslationAnimationDuration(movement,
+ config.filteringCurrentViewsMinAnimDuration));
+ mFilterChildrenAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+ mFilterChildrenAnimator.addListener(new AnimatorListenerAdapter() {
+ boolean isCancelled;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ isCancelled = true;
+ }
+
@Override
public void onAnimationEnd(Animator animation) {
+ if (isCancelled) return;
+
// Return all the removed children to the view pool
for (TaskView tv : childrenToReturnToPool) {
mViewPool.returnViewToPool(tv);
}
// For views that are not already visible, animate them in
+ ArrayList<Animator> newViewsAnims = new ArrayList<Animator>();
int taskCount = tasks.size();
+ int movement = 0;
+ int offset = 0;
for (int i = 0; i < taskCount; i++) {
Task task = tasks.get(i);
TaskViewTransform toTransform = taskTransforms.get(i);
@@ -697,20 +739,38 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskView tv = getChildViewForTask(task);
if (tv == null) {
tv = mViewPool.pickUpViewFromPool(task, task);
+ // Compose a new transform that fades and slides the new task in
+ fromTransform = new TaskViewTransform(toTransform);
+ tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
+ tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
- // Animate from the current position to the new position
- tv.prepareTaskTransformForFilterTaskVisible(fromTransform);
- tv.updateViewPropertiesToTaskTransform(fromTransform,
- toTransform,
- Constants.Values.TaskStackView.Animation.FilteredNewViewsDuration);
+ Animator anim = tv.getAnimatorToTaskTransform(toTransform);
+ anim.setStartDelay(offset *
+ Constants.Values.TaskStackView.FilterStartDelay);
+ newViewsAnims.add(anim);
+
+ // Use the movement of the newly visible views to calculate the duration
+ // of the animation
+ movement = Math.max(movement, Math.abs(toTransform.translationY -
+ fromTransform.translationY));
+ offset++;
}
}
+
+ // Animate the new views in
+ mFilterChildrenAnimator = new AnimatorSet();
+ mFilterChildrenAnimator.setDuration(
+ Utilities.calculateTranslationAnimationDuration(movement,
+ config.filteringNewViewsMinAnimDuration));
+ mFilterChildrenAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+ mFilterChildrenAnimator.playTogether(newViewsAnims);
+ mFilterChildrenAnimator.start();
}
invalidate();
}
});
- childViewAnimSet.playTogether(childViewAnims);
- childViewAnimSet.start();
+ mFilterChildrenAnimator.playTogether(childViewAnims);
+ mFilterChildrenAnimator.start();
}
@Override
@@ -718,16 +778,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Compute the transforms of the items in the current stack
final int curScroll = getStackScroll();
final ArrayList<TaskViewTransform> curTaskTransforms =
- getStackTransforms(curStack, curScroll, null);
+ getStackTransforms(curStack, curScroll, null, true);
// Restore the stashed scroll
updateMinMaxScroll(false);
setStackScrollRaw(mStashedScroll);
boundScrollRaw();
- // Compute the transforms of the items in the new stack
+ // Compute the transforms of the items in the new stack after restoring the stashed scroll
final ArrayList<TaskViewTransform> taskTransforms =
- getStackTransforms(mStack.getTasks(), getStackScroll(), null);
+ getStackTransforms(mStack.getTasks(), getStackScroll(), null, true);
// Animate all of the existing views out of view (if they are not in the visible range in
// the new stack) or to their final positions in the new stack
@@ -735,29 +795,55 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
final ArrayList<Task> tasks = mStack.getTasks();
ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
int childCount = getChildCount();
+ int movement = 0;
for (int i = 0; i < childCount; i++) {
TaskView tv = (TaskView) getChildAt(i);
Task task = tv.getTask();
int taskIndex = tasks.indexOf(task);
- TaskViewTransform transform;
+ TaskViewTransform toTransform;
// If the view is no longer visible, then we should just animate it out
- if (taskIndex < 0 || !taskTransforms.get(taskIndex).visible) {
- transform = new TaskViewTransform(curTaskTransforms.get(curStack.indexOf(task)));
- tv.prepareTaskTransformForFilterTaskVisible(transform);
+ boolean willBeInvisible = taskIndex < 0 || !taskTransforms.get(taskIndex).visible;
+ if (willBeInvisible) {
+ toTransform = new TaskViewTransform(taskTransforms.get(taskIndex));
+ tv.prepareTaskTransformForFilterTaskVisible(toTransform);
childrenToRemove.add(tv);
} else {
- transform = taskTransforms.get(taskIndex);
+ toTransform = taskTransforms.get(taskIndex);
+ // Use the movement of the visible views to calculate the duration of the animation
+ movement = Math.max(movement, Math.abs(toTransform.translationY -
+ (int) tv.getTranslationY()));
}
- childViewAnims.add(tv.getAnimatorToTaskTransform(transform));
+
+ Animator anim = tv.getAnimatorToTaskTransform(toTransform);
+ childViewAnims.add(anim);
+ }
+
+ // Cancel the previous animation
+ if (mFilterChildrenAnimator != null) {
+ mFilterChildrenAnimator.cancel();
+ mFilterChildrenAnimator.removeAllListeners();
}
- AnimatorSet childViewAnimSet = new AnimatorSet();
- childViewAnimSet.setDuration(
- Constants.Values.TaskStackView.Animation.UnfilteredCurrentViewsDuration);
- childViewAnimSet.addListener(new AnimatorListenerAdapter() {
+ // Create a new animation for the existing children
+ final RecentsConfiguration config = RecentsConfiguration.getInstance();
+ mFilterChildrenAnimator = new AnimatorSet();
+ mFilterChildrenAnimator.setDuration(
+ Utilities.calculateTranslationAnimationDuration(movement,
+ config.filteringCurrentViewsMinAnimDuration));
+ mFilterChildrenAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+ mFilterChildrenAnimator.addListener(new AnimatorListenerAdapter() {
+ boolean isCancelled;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ isCancelled = true;
+ }
+
@Override
public void onAnimationEnd(Animator animation) {
+ if (isCancelled) return;
+
// Return all the removed children to the view pool
for (TaskView tv : childrenToRemove) {
mViewPool.returnViewToPool(tv);
@@ -768,8 +854,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// For views that are not already visible, animate them in
ArrayList<Animator> newViewAnims = new ArrayList<Animator>();
- AnimatorSet newViewAnimSet = new AnimatorSet();
int taskCount = tasks.size();
+ int movement = 0;
int offset = 0;
for (int i = 0; i < taskCount; i++) {
Task task = tasks.get(i);
@@ -780,34 +866,46 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// For views that are not already visible, animate them in
tv = mViewPool.pickUpViewFromPool(task, task);
- // Animate in this new view
+ // Compose a new transform to fade and slide the new task in
TaskViewTransform fromTransform = new TaskViewTransform(toTransform);
tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
- newViewAnims.add(tv.getAnimatorToTaskTransform(toTransform));
+
+ Animator anim = tv.getAnimatorToTaskTransform(toTransform);
+ anim.setStartDelay(offset *
+ Constants.Values.TaskStackView.FilterStartDelay);
+ newViewAnims.add(anim);
+ // Use the movement of the newly visible views to calculate the duration
+ // of the animation
+ movement = Math.max(movement,
+ Math.abs(toTransform.translationY - fromTransform.translationY));
offset++;
}
}
}
// Run the animation
- newViewAnimSet.setDuration(
- Constants.Values.TaskStackView.Animation.UnfilteredNewViewsDuration);
- newViewAnimSet.playTogether(newViewAnims);
- newViewAnimSet.addListener(new AnimatorListenerAdapter() {
+ mFilterChildrenAnimator = new AnimatorSet();
+ mFilterChildrenAnimator.setDuration(
+ Utilities.calculateTranslationAnimationDuration(movement,
+ config.filteringNewViewsMinAnimDuration));
+ mFilterChildrenAnimator.playTogether(newViewAnims);
+ mFilterChildrenAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// Decrement the hw layers ref count
decHwLayersRefCount("unfilteredNewViews");
}
});
- newViewAnimSet.start();
-
+ mFilterChildrenAnimator.start();
invalidate();
}
});
- childViewAnimSet.playTogether(childViewAnims);
- childViewAnimSet.start();
+ mFilterChildrenAnimator.playTogether(childViewAnims);
+ mFilterChildrenAnimator.start();
+
+ // Clear the saved vars
+ mStashedScroll = 0;
}
/**** ViewPoolConsumer Implementation ****/
@@ -1056,7 +1154,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP: {
// Animate the scroll back if we've cancelled
- mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
+ mSv.animateBoundScroll();
// Disable HW layers
if (mIsScrolling) {
mSv.decHwLayersRefCount("stackScroll");
@@ -1186,7 +1284,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
} else if (mSv.isScrollOutOfBounds()) {
// Animate the scroll back into bounds
// XXX: Make this animation a function of the velocity OR distance
- mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
+ mSv.animateBoundScroll();
}
if (mIsScrolling) {
@@ -1220,7 +1318,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
if (mSv.isScrollOutOfBounds()) {
// Animate the scroll back into bounds
// XXX: Make this animation a function of the velocity OR distance
- mSv.animateBoundScroll(Constants.Values.TaskStackView.Animation.SnapScrollBackDuration);
+ mSv.animateBoundScroll();
}
mActivePointerId = INACTIVE_POINTER_ID;
mIsScrolling = false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 2c27d44..e99fecb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -20,20 +20,24 @@ import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import com.android.systemui.R;
+import com.android.systemui.recents.BakedBezierInterpolator;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
+import com.android.systemui.recents.Utilities;
import com.android.systemui.recents.model.Task;
+import java.util.Random;
+
/* A task view */
public class TaskView extends FrameLayout implements View.OnClickListener, Task.TaskCallbacks {
@@ -131,7 +135,7 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
.scaleY(toTransform.scale)
.alpha(toTransform.alpha)
.setDuration(duration)
- .setInterpolator(new AccelerateDecelerateInterpolator())
+ .setInterpolator(BakedBezierInterpolator.INSTANCE)
.withLayer()
.start();
} else {
@@ -190,7 +194,8 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
.translationX(0)
.translationY(0)
.setStartDelay(235)
- .setDuration(Constants.Values.TaskView.Animation.TaskIconOnEnterDuration)
+ .setInterpolator(BakedBezierInterpolator.INSTANCE)
+ .setDuration(Utilities.calculateTranslationAnimationDuration(translate))
.withLayer()
.start();
}
@@ -206,8 +211,8 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
.translationX(translate / 2)
.translationY(-translate)
.setStartDelay(0)
- .setDuration(Constants.Values.TaskView.Animation.TaskIconOnLeavingDuration)
- .setInterpolator(new DecelerateInterpolator())
+ .setInterpolator(BakedBezierInterpolator.INSTANCE)
+ .setDuration(Utilities.calculateTranslationAnimationDuration(translate))
.withLayer()
.withEndAction(r)
.start();