diff options
author | Winson Chung <winsonc@google.com> | 2014-09-16 00:58:25 +0200 |
---|---|---|
committer | Jorim Jaggi <jjaggi@google.com> | 2014-09-18 18:34:17 +0000 |
commit | bf5dbf1c151eb64f4068f233e72b0a867348bf8c (patch) | |
tree | 1fb99527e585c514c8841e8aaf10a948c22490fa /packages/SystemUI/src/com/android/systemui/recents | |
parent | a8433c6512cc53fb0eef58181e364b4ba330811c (diff) | |
download | frameworks_base-bf5dbf1c151eb64f4068f233e72b0a867348bf8c.zip frameworks_base-bf5dbf1c151eb64f4068f233e72b0a867348bf8c.tar.gz frameworks_base-bf5dbf1c151eb64f4068f233e72b0a867348bf8c.tar.bz2 |
Enabling recents stack clipping
The taskviews now avoid overdraw by clipping invisible
parts. Also adapted some timings of the animation.
Bug: 17455301
Change-Id: Ifbf7bab363e530cb2ad842baed50fc16dcfcc4c4
Diffstat (limited to 'packages/SystemUI/src/com/android/systemui/recents')
10 files changed, 197 insertions, 48 deletions
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 |