summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/res/layout/recents_task_view.xml43
-rw-r--r--packages/SystemUI/res/values/config.xml9
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Constants.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java77
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java3
12 files changed, 227 insertions, 70 deletions
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 1b982fb..d1d3828 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -18,26 +18,31 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true">
- <com.android.systemui.recents.views.TaskViewThumbnail
- android:id="@+id/task_view_thumbnail"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- <include layout="@layout/recents_task_view_header" />
<FrameLayout
- android:id="@+id/lock_to_app_fab"
- android:layout_width="48dp"
- android:layout_height="48dp"
- android:layout_gravity="bottom|right"
- android:layout_marginRight="15dp"
- android:layout_marginBottom="15dp"
- android:translationZ="3dp"
- android:contentDescription="@string/recents_lock_to_app_button_label"
- android:background="@drawable/recents_lock_to_task_button_bg">
- <ImageView
- android:layout_width="24dp"
- android:layout_height="24dp"
- android:layout_gravity="center"
- android:src="@drawable/recents_lock_to_app_pin" />
+ android:id="@+id/task_view_content"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <com.android.systemui.recents.views.TaskViewThumbnail
+ android:id="@+id/task_view_thumbnail"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+ <include layout="@layout/recents_task_view_header" />
+ <FrameLayout
+ android:id="@+id/lock_to_app_fab"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_gravity="bottom|right"
+ android:layout_marginRight="15dp"
+ android:layout_marginBottom="15dp"
+ android:translationZ="2dp"
+ android:contentDescription="@string/recents_lock_to_app_button_label"
+ android:background="@drawable/recents_lock_to_task_button_bg">
+ <ImageView
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_gravity="center"
+ android:src="@drawable/recents_lock_to_app_pin" />
+ </FrameLayout>
</FrameLayout>
</com.android.systemui.recents.views.TaskView>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index e0cddb8..9346906 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -154,9 +154,12 @@
duration of the transition in to recents from home. -->
<integer name="recents_animate_task_enter_from_home_delay">150</integer>
<!-- The min animation duration for animating the task in when transitioning from home. -->
- <integer name="recents_animate_task_enter_from_home_duration">275</integer>
- <!-- The animation stagger to apply to each task animation when transitioning from home. -->
- <integer name="recents_animate_task_enter_from_home_stagger_delay">10</integer>
+ <integer name="recents_animate_task_enter_from_home_duration">200</integer>
+ <!-- The total animation stagger delay when entering from home. -->
+ <integer name="recents_animate_task_enter_from_home_stagger_delay">110</integer>
+ <!-- The total animation duration added to the last card when entering from home.
+ This value is partialy also added to the previous tasks -->
+ <integer name="recents_animate_task_enter_from_home_stagger_duration">72</integer>
<!-- The short duration when animating in/out the lock to app button. -->
<integer name="recents_animate_lock_to_app_button_short_duration">150</integer>
<!-- The long duration when animating in/out the lock to app button. -->
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index e4a167b..103f96f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -32,7 +32,7 @@ public class Constants {
// Enables the filtering of tasks according to their grouping
public static final boolean EnableTaskFiltering = false;
// Enables clipping of tasks against each other
- public static final boolean EnableTaskStackClipping = false;
+ public static final boolean EnableTaskStackClipping = true;
// Enables tapping on the TaskBar to launch the task
public static final boolean EnableTaskBarTouchEvents = true;
// Enables app-info pane on long-pressing the icon
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index e3a2ad8..4696c82 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -78,6 +78,7 @@ public class RecentsConfiguration {
public int taskViewEnterFromHomeDelay;
public int taskViewEnterFromHomeDuration;
public int taskViewEnterFromHomeStaggerDelay;
+ public int taskViewEnterFromHomeStaggerDuration;
public int taskViewExitToHomeDuration;
public int taskViewRemoveAnimDuration;
public int taskViewRemoveAnimTranslationXPx;
@@ -219,6 +220,8 @@ public class RecentsConfiguration {
res.getInteger(R.integer.recents_animate_task_enter_from_home_duration);
taskViewEnterFromHomeStaggerDelay =
res.getInteger(R.integer.recents_animate_task_enter_from_home_stagger_delay);
+ taskViewEnterFromHomeStaggerDuration =
+ res.getInteger(R.integer.recents_animate_task_enter_from_home_stagger_duration);
taskViewExitToHomeDuration =
res.getInteger(R.integer.recents_animate_task_exit_to_home_duration);
taskViewRemoveAnimDuration =
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index 4c6b389..f01d17c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -18,11 +18,14 @@ package com.android.systemui.recents.misc;
import android.content.Intent;
import android.graphics.Color;
+import android.graphics.Matrix;
import android.graphics.Rect;
+import android.view.View;
import com.android.systemui.recents.RecentsConfiguration;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.ArrayList;
/* Common code */
public class Utilities {
@@ -68,6 +71,80 @@ public class Utilities {
}
}
+ /** Maps a coorindate in a descendant view into the parent. */
+ public static float mapCoordInDescendentToSelf(View descendant, View root,
+ float[] coord, boolean includeRootScroll) {
+ ArrayList<View> ancestorChain = new ArrayList<View>();
+
+ float[] pt = {coord[0], coord[1]};
+
+ View v = descendant;
+ while(v != root && v != null) {
+ ancestorChain.add(v);
+ v = (View) v.getParent();
+ }
+ ancestorChain.add(root);
+
+ float scale = 1.0f;
+ int count = ancestorChain.size();
+ for (int i = 0; i < count; i++) {
+ View v0 = ancestorChain.get(i);
+ // For TextViews, scroll has a meaning which relates to the text position
+ // which is very strange... ignore the scroll.
+ if (v0 != descendant || includeRootScroll) {
+ pt[0] -= v0.getScrollX();
+ pt[1] -= v0.getScrollY();
+ }
+
+ v0.getMatrix().mapPoints(pt);
+ pt[0] += v0.getLeft();
+ pt[1] += v0.getTop();
+ scale *= v0.getScaleX();
+ }
+
+ coord[0] = pt[0];
+ coord[1] = pt[1];
+ return scale;
+ }
+
+ /** Maps a coordinate in the root to a descendent. */
+ public static float mapCoordInSelfToDescendent(View descendant, View root,
+ float[] coord, Matrix tmpInverseMatrix) {
+ ArrayList<View> ancestorChain = new ArrayList<View>();
+
+ float[] pt = {coord[0], coord[1]};
+
+ View v = descendant;
+ while(v != root) {
+ ancestorChain.add(v);
+ v = (View) v.getParent();
+ }
+ ancestorChain.add(root);
+
+ float scale = 1.0f;
+ int count = ancestorChain.size();
+ tmpInverseMatrix.set(Matrix.IDENTITY_MATRIX);
+ for (int i = count - 1; i >= 0; i--) {
+ View ancestor = ancestorChain.get(i);
+ View next = i > 0 ? ancestorChain.get(i-1) : null;
+
+ pt[0] += ancestor.getScrollX();
+ pt[1] += ancestor.getScrollY();
+
+ if (next != null) {
+ pt[0] -= next.getLeft();
+ pt[1] -= next.getTop();
+ next.getMatrix().invert(tmpInverseMatrix);
+ tmpInverseMatrix.mapPoints(pt);
+ scale *= next.getScaleX();
+ }
+ }
+
+ coord[0] = pt[0];
+ coord[1] = pt[1];
+ return scale;
+ }
+
/** Calculates the constrast between two colors, using the algorithm provided by the WCAG v2. */
public static float computeContrastBetweenColors(int bg, int fg) {
float bgR = Color.red(bg) / 255f;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
index b584fd3..d2fdaff 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -22,6 +22,7 @@ import android.graphics.Outline;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewOutlineProvider;
+
import com.android.systemui.recents.RecentsConfiguration;
/* An outline provider that has a clip and outline that can be animated. */
@@ -29,8 +30,10 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
RecentsConfiguration mConfig;
- View mSourceView;
+ TaskView mSourceView;
+ Rect mTmpRect = new Rect();
Rect mClipRect = new Rect();
+ Rect mClipBounds = new Rect();
Rect mOutlineClipRect = new Rect();
int mCornerRadius;
float mAlpha = 1f;
@@ -40,7 +43,7 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
ObjectAnimator mClipRightAnimator;
ObjectAnimator mClipBottomAnimator;
- public AnimateableViewBounds(View source, int cornerRadius) {
+ public AnimateableViewBounds(TaskView source, int cornerRadius) {
mConfig = RecentsConfiguration.getInstance();
mSourceView = source;
mCornerRadius = cornerRadius;
@@ -53,8 +56,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
@Override
public void getOutline(View view, Outline outline) {
outline.setAlpha(mMinAlpha + mAlpha / (1f - mMinAlpha));
-
- // TODO: This doesn't work with fake shadows.
outline.setRoundRect(Math.max(mClipRect.left, mOutlineClipRect.left),
Math.max(mClipRect.top, mOutlineClipRect.top),
mSourceView.getWidth() - Math.max(mClipRect.right, mOutlineClipRect.right),
@@ -90,6 +91,7 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
if (top != mClipRect.top) {
mClipRect.top = top;
mSourceView.invalidateOutline();
+ updateClipBounds();
}
}
@@ -115,6 +117,7 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
if (right != mClipRect.right) {
mClipRect.right = right;
mSourceView.invalidateOutline();
+ updateClipBounds();
}
}
@@ -140,6 +143,11 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
if (bottom != mClipRect.bottom) {
mClipRect.bottom = bottom;
mSourceView.invalidateOutline();
+ updateClipBounds();
+ if (!mConfig.useHardwareLayers) {
+ mSourceView.mThumbnailView.updateVisibility(
+ bottom - mSourceView.getPaddingBottom());
+ }
}
}
@@ -160,4 +168,11 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
public int getOutlineClipBottom() {
return mOutlineClipRect.bottom;
}
+
+ private void updateClipBounds() {
+ mClipBounds.set(mClipRect.left, mClipRect.top,
+ mSourceView.getWidth() - mClipRect.right,
+ mSourceView.getHeight() - mClipRect.bottom);
+ mSourceView.setClipBounds(mClipBounds);
+ }
}
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 470b1f0..e1e4068 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -16,21 +16,23 @@
package com.android.systemui.recents.views;
+import android.animation.ValueAnimator;
import android.content.ComponentName;
import android.content.Context;
+import android.graphics.Matrix;
import android.graphics.Rect;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
-import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.RecentsPackageMonitor;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
@@ -76,16 +78,28 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Optimizations
int mStackViewsAnimationDuration;
boolean mStackViewsDirty = true;
+ boolean mStackViewsClipDirty = true;
boolean mAwaitingFirstLayout = true;
boolean mStartEnterAnimationRequestedAfterLayout;
boolean mStartEnterAnimationCompleted;
ViewAnimation.TaskViewEnterContext mStartEnterAnimationContext;
int[] mTmpVisibleRange = new int[2];
+ float[] mTmpCoord = new float[2];
+ Matrix mTmpMatrix = new Matrix();
Rect mTmpRect = new Rect();
TaskViewTransform mTmpTransform = new TaskViewTransform();
HashMap<Task, TaskView> mTmpTaskViewMap = new HashMap<Task, TaskView>();
LayoutInflater mInflater;
+ // A convenience update listener to request updating clipping of tasks
+ ValueAnimator.AnimatorUpdateListener mRequestUpdateClippingListener =
+ new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ requestUpdateStackViewsClip();
+ }
+ };
+
// A convenience runnable to return all views to the pool
Runnable mReturnAllViewsToPoolRunnable = new Runnable() {
@Override
@@ -152,6 +166,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
+ /** Requests that the views clipping be updated. */
+ void requestUpdateStackViewsClip() {
+ if (!mStackViewsClipDirty) {
+ invalidate();
+ mStackViewsClipDirty = true;
+ }
+ }
+
/** Finds the child view given a specific task. */
public TaskView getChildViewForTask(Task t) {
int childCount = getChildCount();
@@ -301,7 +323,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Animate the task into place
tv.updateViewPropertiesToTaskTransform(mCurrentTaskTransforms.get(taskIndex),
- mStackViewsAnimationDuration);
+ mStackViewsAnimationDuration, mRequestUpdateClippingListener);
// Request accessibility focus on the next view if we removed the task
// that previously held accessibility focus
@@ -319,6 +341,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Reset the request-synchronize params
mStackViewsAnimationDuration = 0;
mStackViewsDirty = false;
+ mStackViewsClipDirty = true;
return true;
}
return false;
@@ -349,10 +372,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// stacked and we can make assumptions about the visibility of the this
// task relative to the ones in front of it.
if (nextTv != null) {
- // We can reuse the current task transforms to find the task rects
- TaskViewTransform transform = mCurrentTaskTransforms.get(mStack.indexOfTask(tv.getTask()));
- TaskViewTransform nextTransform = mCurrentTaskTransforms.get(mStack.indexOfTask(nextTv.getTask()));
- clipBottom = transform.rect.bottom - nextTransform.rect.top;
+ // Map the top edge of next task view into the local space of the current
+ // task view to find the clip amount in local space
+ mTmpCoord[0] = mTmpCoord[1] = 0;
+ Utilities.mapCoordInDescendentToSelf(nextTv, this, mTmpCoord, false);
+ Utilities.mapCoordInSelfToDescendent(tv, this, mTmpCoord, mTmpMatrix);
+ clipBottom = (int) Math.floor(tv.getMeasuredHeight() - mTmpCoord[1]
+ - nextTv.getPaddingTop() - 1);
}
}
tv.getViewBounds().setClipBottom(clipBottom);
@@ -363,6 +389,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
tv.getViewBounds().setClipBottom(0);
}
}
+ mStackViewsClipDirty = false;
}
/** The stack insets to apply to the stack contents */
@@ -665,6 +692,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
ctx.currentTaskRect = mLayoutAlgorithm.mTaskRect;
ctx.currentTaskOccludesLaunchTarget = (launchTargetTask != null) &&
launchTargetTask.group.isTaskAboveTask(task, launchTargetTask);
+ ctx.updateListener = mRequestUpdateClippingListener;
mLayoutAlgorithm.getStackTransform(task, mStackScroller.getStackScroll(), ctx.currentTaskTransform, null);
tv.startEnterRecentsAnimation(ctx);
}
@@ -1003,7 +1031,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
@Override
public void onTaskViewClipStateChanged(TaskView tv) {
- invalidate();
+ if (!mStackViewsDirty) {
+ invalidate();
+ }
}
@Override
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 4baf31f..1750804 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -20,12 +20,7 @@ import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
-import android.graphics.Color;
-import android.graphics.Outline;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.Rect;
+import android.graphics.*;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
@@ -74,6 +69,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
AnimateableViewBounds mViewBounds;
Paint mLayerPaint = new Paint();
+ View mContent;
TaskViewThumbnail mThumbnailView;
TaskViewHeader mHeaderView;
TaskViewFooter mFooterView;
@@ -134,15 +130,16 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
@Override
protected void onFinishInflate() {
// Bind the views
+ mContent = findViewById(R.id.task_view_content);
mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar);
mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail);
+ mThumbnailView.enableTaskBarClip(mHeaderView);
mActionButtonView = findViewById(R.id.lock_to_app_fab);
mActionButtonView.setOutlineProvider(new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
// Set the outline to match the FAB background
- outline.setOval(0, 0, mActionButtonView.getWidth(),
- mActionButtonView.getHeight());
+ outline.setOval(0, 0, mActionButtonView.getWidth(), mActionButtonView.getHeight());
}
});
if (mFooterView != null) {
@@ -157,6 +154,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
int widthWithoutPadding = width - mPaddingLeft - mPaddingRight;
int heightWithoutPadding = height - mPaddingTop - mPaddingBottom;
+
+ // Measure the content
+ mContent.measure(MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY));
+
// Measure the bar view, thumbnail, and footer
mHeaderView.measure(MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mConfig.taskBarHeight, MeasureSpec.EXACTLY));
@@ -186,6 +188,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Synchronizes this view's properties with the task's transform */
void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform, int duration) {
+ updateViewPropertiesToTaskTransform(toTransform, duration, null);
+ }
+
+ void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform, int duration,
+ ValueAnimator.AnimatorUpdateListener updateCallback) {
// If we are a full screen view, then only update the Z to keep it in order
// XXX: Also update/animate the dim as well
if (mIsFullScreenView) {
@@ -198,7 +205,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
// Apply the transform
toTransform.applyToTaskView(this, duration, mConfig.fastOutSlowInInterpolator, false,
- !mConfig.fakeShadows);
+ !mConfig.fakeShadows, updateCallback);
// Update the task progress
if (mTaskProgressAnimator != null) {
@@ -331,8 +338,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mViewBounds.setClipRight(0);
// Reset the bar translation
mHeaderView.setTranslationY(0);
- // Enable the thumbnail clip
- mThumbnailView.enableTaskBarClip(mHeaderView);
// Animate the footer into view (if it is the front most task)
animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration);
@@ -349,9 +354,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
})
.start();
} else {
- // Otherwise, just enable the thumbnail clip
- mThumbnailView.enableTaskBarClip(mHeaderView);
-
// Animate the footer into view
animateFooterVisibility(true, 0);
}
@@ -359,8 +361,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
} else if (mConfig.launchedFromAppWithThumbnail) {
if (mTask.isLaunchTarget) {
- // Enable the task bar clip
- mThumbnailView.enableTaskBarClip(mHeaderView);
// Animate the dim/overlay
if (Constants.DebugFlags.App.EnableThumbnailAlphaOnFrontmost) {
// Animate the thumbnail alpha before the dim animation (to prevent updating the
@@ -392,8 +392,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
.withLayer()
.start();
} else {
- // Enable the task bar clip
- mThumbnailView.enableTaskBarClip(mHeaderView);
// Animate the task up if it was occluding the launch target
if (ctx.currentTaskOccludesLaunchTarget) {
setTranslationY(transform.translationY + mConfig.taskViewAffiliateGroupEnterOffsetPx);
@@ -407,7 +405,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
.withEndAction(new Runnable() {
@Override
public void run() {
- mThumbnailView.enableTaskBarClip(mHeaderView);
// Decrement the post animation trigger
ctx.postAnimationTrigger.decrement();
}
@@ -421,8 +418,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
} else if (mConfig.launchedFromHome) {
// Animate the tasks up
int frontIndex = (ctx.currentStackViewCount - ctx.currentStackViewIndex - 1);
- int delay = mConfig.taskViewEnterFromHomeDelay +
- frontIndex * mConfig.taskViewEnterFromHomeStaggerDelay;
+ float fraction = (float) frontIndex / (ctx.currentStackViewCount - 1);
+ fraction = (float) Math.pow(fraction, 0.85f);
+ int delay = (int) (mConfig.taskViewEnterFromHomeDelay +
+ fraction * mConfig.taskViewEnterFromHomeStaggerDelay);
+ long delayIncrease = (long) (fraction * mConfig.taskViewEnterFromHomeStaggerDuration);
if (!mConfig.fakeShadows) {
animate().translationZ(transform.translationZ);
}
@@ -431,13 +431,12 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
.scaleY(transform.scale)
.translationY(transform.translationY)
.setStartDelay(delay)
- .setUpdateListener(null)
+ .setUpdateListener(ctx.updateListener)
.setInterpolator(mConfig.quintOutInterpolator)
- .setDuration(mConfig.taskViewEnterFromHomeDuration)
+ .setDuration(mConfig.taskViewEnterFromHomeDuration + delayIncrease)
.withEndAction(new Runnable() {
@Override
public void run() {
- mThumbnailView.enableTaskBarClip(mHeaderView);
// Decrement the post animation trigger
ctx.postAnimationTrigger.decrement();
}
@@ -450,9 +449,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
startDelay = delay;
} else {
- // Otherwise, just enable the thumbnail clip
- mThumbnailView.enableTaskBarClip(mHeaderView);
-
// Animate the footer into view
animateFooterVisibility(true, 0);
}
@@ -484,8 +480,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
void startLaunchTaskAnimation(final Runnable postAnimRunnable, boolean isLaunchingTask,
boolean occludesLaunchTarget, boolean lockToTask) {
if (isLaunchingTask) {
- // Disable the thumbnail clip
- mThumbnailView.disableTaskBarClip();
// Animate the thumbnail alpha back into full opacity for the window animation out
mThumbnailView.startLaunchTaskAnimation(postAnimRunnable);
@@ -662,7 +656,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
int inverse = 255 - mDim;
mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse));
mLayerPaint.setColorFilter(mDimColorFilter);
- setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
+ mContent.setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
}
} else {
float dimAlpha = mDim / 255.0f;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index fd39126..396d441 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -259,6 +259,14 @@ public class TaskViewHeader extends FrameLayout {
}
}
+ @Override
+ protected int[] onCreateDrawableState(int extraSpace) {
+
+ // Don't forward our state to the drawable - we do it manually in onTaskViewFocusChanged.
+ // This is to prevent layer trashing when the view is pressed.
+ return new int[] {};
+ }
+
/** Notifies the associated TaskView has been focused. */
void onTaskViewFocusChanged(boolean focused) {
boolean isRunning = false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index 11ca103..a946a84 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -52,6 +52,8 @@ public class TaskViewThumbnail extends View {
private BitmapShader mBitmapShader;
private float mBitmapAlpha;
private float mDimAlpha;
+ private View mTaskBar;
+ private boolean mInvisible;
private ValueAnimator mAlphaAnimator;
private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener
= new ValueAnimator.AnimatorUpdateListener() {
@@ -85,6 +87,9 @@ public class TaskViewThumbnail extends View {
@Override
protected void onDraw(Canvas canvas) {
+ if (mInvisible) {
+ return;
+ }
canvas.drawRoundRect(0,
0,
getWidth(),
@@ -101,6 +106,9 @@ public class TaskViewThumbnail extends View {
}
private void updateFilter() {
+ if (mInvisible) {
+ return;
+ }
int mul = (int) ((1.0f - mDimAlpha) * mBitmapAlpha * 255);
int add = (int) ((1.0f - mDimAlpha) * (1 - mBitmapAlpha) * 255);
if (mBitmapShader != null) {
@@ -118,16 +126,22 @@ public class TaskViewThumbnail extends View {
/** Updates the clip rect based on the given task bar. */
void enableTaskBarClip(View taskBar) {
+ mTaskBar = taskBar;
int top = (int) Math.max(0, taskBar.getTranslationY() +
taskBar.getMeasuredHeight() - 1);
mClipRect.set(0, top, getMeasuredWidth(), getMeasuredHeight());
setClipBounds(mClipRect);
}
- /** Disables the task bar clipping. */
- void disableTaskBarClip() {
- mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
- setClipBounds(mClipRect);
+ void updateVisibility(int clipBottom) {
+ boolean invisible = mTaskBar != null && getHeight() - clipBottom < mTaskBar.getHeight();
+ if (invisible != mInvisible) {
+ mInvisible = invisible;
+ if (!mInvisible) {
+ updateFilter();
+ }
+ invalidate();
+ }
}
/** Binds the thumbnail view to the screenshot. */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index fee4e80..42c0f9f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -78,7 +78,7 @@ public class TaskViewTransform {
/** Applies this transform to a view. */
public void applyToTaskView(View v, int duration, Interpolator interp, boolean allowLayers,
- boolean allowShadows) {
+ boolean allowShadows, ValueAnimator.AnimatorUpdateListener updateCallback) {
// Check to see if any properties have changed, and update the task view
if (duration > 0) {
ViewPropertyAnimator anim = v.animate();
@@ -104,6 +104,11 @@ public class TaskViewTransform {
if (requiresLayers && allowLayers) {
anim.withLayer();
}
+ if (updateCallback != null) {
+ anim.setUpdateListener(updateCallback);
+ } else {
+ anim.setUpdateListener(null);
+ }
anim.setStartDelay(startDelay)
.setDuration(duration)
.setInterpolator(interp)
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
index a1fc40f..4586f12 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
@@ -16,6 +16,7 @@
package com.android.systemui.recents.views;
+import android.animation.ValueAnimator;
import android.graphics.Rect;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
@@ -27,6 +28,8 @@ public class ViewAnimation {
// A trigger to run some logic when all the animations complete. This works around the fact
// that it is difficult to coordinate ViewPropertyAnimators
ReferenceCountedTrigger postAnimationTrigger;
+ // An update listener to notify as the enter animation progresses (used for the home transition)
+ ValueAnimator.AnimatorUpdateListener updateListener;
// These following properties are updated for each task view we start the enter animation on