diff options
12 files changed, 199 insertions, 209 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index a0c481a17375..34353bc8b1b5 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -26,7 +26,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.ActivityInfo; import android.net.Uri; import android.os.Bundle; import android.os.SystemClock; @@ -62,8 +61,6 @@ import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent; import com.android.systemui.recents.events.ui.StackViewScrolledEvent; import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent; import com.android.systemui.recents.events.ui.UserInteractionEvent; -import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent; -import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent; import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent; import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent; import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent; diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index d1e8faea65e3..3efb0cc846ae 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -35,7 +35,6 @@ import android.util.MutableBoolean; import android.view.AppTransitionAnimationSpec; import android.view.LayoutInflater; import android.view.View; - import com.android.internal.logging.MetricsLogger; import com.android.systemui.Prefs; import com.android.systemui.R; diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java index eb81e8040714..d72218fd3366 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java +++ b/packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java @@ -761,7 +761,7 @@ public class EventBus extends BroadcastReceiver { } catch (IllegalAccessException e) { Log.e(TAG, "Failed to invoke method", e.getCause()); } catch (InvocationTargetException e) { - throw new RuntimeException("Failed to invoke method", e); + throw new RuntimeException(e.getCause()); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java index 913d42751c1c..2eee1da10781 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java @@ -18,7 +18,6 @@ package com.android.systemui.recents.history; import android.app.ActivityOptions; import android.content.Context; -import android.content.res.Resources; import android.support.v7.widget.RecyclerView; import android.text.format.DateFormat; import android.view.LayoutInflater; @@ -29,7 +28,6 @@ import com.android.systemui.R; import com.android.systemui.recents.Recents; import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.recents.model.Task; -import com.android.systemui.recents.model.TaskStack; import java.util.ArrayList; import java.util.Calendar; diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java index 9d3a99fc9e1d..58511110d452 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java @@ -27,7 +27,6 @@ import android.view.WindowInsets; import android.view.animation.AnimationUtils; import android.view.animation.Interpolator; import android.widget.LinearLayout; - import com.android.systemui.R; import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsConfiguration; 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 271a2a09d8e5..757d2aa9111c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java @@ -69,7 +69,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider { */ public void reset() { mClipRect.setEmpty(); - mSourceView.invalidateOutline(); updateClipBounds(); } @@ -94,7 +93,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider { public void setClipBottom(int bottom, boolean force) { if (bottom != mClipRect.bottom || force) { mClipRect.bottom = bottom; - mSourceView.invalidateOutline(); updateClipBounds(); } } @@ -108,7 +106,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider { public void setClipRight(int right, boolean force) { if (right != mClipRect.right || force) { mClipRect.right = right; - mSourceView.invalidateOutline(); updateClipBounds(); } } @@ -123,5 +120,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider { mSourceView.getWidth() - mClipRect.right, mSourceView.getHeight() - mClipRect.bottom); mSourceView.setClipBounds(mClipBounds); + mSourceView.invalidateOutline(); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java index 6c0d6db507dd..9b9d58c9114d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java @@ -16,12 +16,13 @@ package com.android.systemui.recents.views; -import android.graphics.Bitmap; import android.graphics.Rect; +import android.graphics.RectF; import android.util.Log; import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.Task; +import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -33,48 +34,91 @@ public class FreeformWorkspaceLayoutAlgorithm { private static final String TAG = "FreeformWorkspaceLayoutAlgorithm"; private static final boolean DEBUG = false; - // The number of cells in the freeform workspace - private int mFreeformCellXCount; - private int mFreeformCellYCount; - - // The width and height of the cells in the freeform workspace - private int mFreeformCellWidth; - private int mFreeformCellHeight; - - // Optimization, allows for quick lookup of task -> index - private HashMap<Task.TaskKey, Integer> mTaskIndexMap = new HashMap<>(); + // Optimization, allows for quick lookup of task -> rect + private HashMap<Task.TaskKey, RectF> mTaskRectMap = new HashMap<>(); /** * Updates the layout for each of the freeform workspace tasks. This is called after the stack * layout is updated. */ public void update(List<Task> freeformTasks, TaskStackLayoutAlgorithm stackLayout) { - mTaskIndexMap.clear(); + Collections.reverse(freeformTasks); + mTaskRectMap.clear(); int numFreeformTasks = stackLayout.mNumFreeformTasks; if (!freeformTasks.isEmpty()) { - // Calculate the cell width/height depending on the number of freeform tasks - mFreeformCellXCount = Math.max(1, (int) Math.ceil(Math.sqrt(numFreeformTasks))); - mFreeformCellYCount = Math.max(1, (int) Math.ceil((float) numFreeformTasks / - mFreeformCellXCount)); - // For now, make the cells square - mFreeformCellWidth = Math.min(stackLayout.mFreeformRect.width() / mFreeformCellXCount, - stackLayout.mFreeformRect.height() / mFreeformCellYCount); - mFreeformCellHeight = mFreeformCellWidth; - // Put each of the tasks in the progress map at a fixed index (does not need to actually - // map to a scroll position, just by index) - int taskCount = freeformTasks.size(); - for (int i = taskCount - 1; i >= 0; i--) { + // Normalize the widths so that we can calculate the best layout below + int workspaceWidth = stackLayout.mFreeformRect.width(); + int workspaceHeight = stackLayout.mFreeformRect.height(); + float normalizedWorkspaceWidth = (float) workspaceWidth / workspaceHeight; + float normalizedWorkspaceHeight = 1f; + float[] normalizedTaskWidths = new float[numFreeformTasks]; + for (int i = 0; i < numFreeformTasks; i++) { Task task = freeformTasks.get(i); - mTaskIndexMap.put(task.key, taskCount - i - 1); + float rowTaskWidth; + if (task.bounds != null) { + rowTaskWidth = (float) task.bounds.width() / task.bounds.height(); + } else { + // If this is a stack task that was dragged into the freeform workspace, then + // the task will not yet have an associated bounds, so assume the full workspace + // width for the time being + rowTaskWidth = normalizedWorkspaceWidth; + } + // Bound the task width to the workspace width so that at the worst case, it will + // fit its own row + normalizedTaskWidths[i] = Math.min(rowTaskWidth, + normalizedWorkspaceWidth); } - if (DEBUG) { - Log.d(TAG, "mFreeformCellXCount: " + mFreeformCellXCount); - Log.d(TAG, "mFreeformCellYCount: " + mFreeformCellYCount); - Log.d(TAG, "mFreeformCellWidth: " + mFreeformCellWidth); - Log.d(TAG, "mFreeformCellHeight: " + mFreeformCellHeight); + // Determine the scale to best fit each of the tasks in the workspace + float rowScale = 0.85f; + float rowWidth = 0f; + float maxRowWidth = 0f; + int rowCount = 1; + for (int i = 0; i < numFreeformTasks;) { + float width = normalizedTaskWidths[i] * rowScale; + if (rowWidth + width > normalizedWorkspaceWidth) { + // That is too long for this row, create new row + rowWidth = 0f; + if ((rowCount + 1) * rowScale > normalizedWorkspaceHeight) { + // The new row is too high, so we need to try fitting again. Update the + // scale to be the smaller of the scale needed to fit the task in the + // previous row, or the scale needed to fit the new row + rowScale = Math.min(normalizedWorkspaceWidth / (rowWidth + width), + normalizedWorkspaceHeight / (rowCount + 1)); + rowCount = 1; + i = 0; + } else { + // The new row fits, so continue + rowCount++; + i++; + } + } else { + // Task is OK in this row + rowWidth += width; + i++; + } + maxRowWidth = Math.max(rowWidth, maxRowWidth); + } + + // Normalize each of the actual rects to that scale + int height = (int) (rowScale * workspaceHeight); + float rowTop = ((1f - (rowScale * rowCount)) * workspaceHeight) / 2f; + float defaultRowLeft = ((1f - (maxRowWidth / normalizedWorkspaceWidth)) * + workspaceWidth) / 2f; + float rowLeft = defaultRowLeft; + for (int i = 0; i < numFreeformTasks; i++) { + Task task = freeformTasks.get(i); + int width = (int) (height * normalizedTaskWidths[i]); + if (rowLeft + width > workspaceWidth) { + // This goes on the next line + rowTop += height; + rowLeft = defaultRowLeft; + } + RectF rect = new RectF(rowLeft, rowTop, rowLeft + width, rowTop + height); + rowLeft += width; + mTaskRectMap.put(task.key, rect); } } } @@ -86,7 +130,7 @@ public class FreeformWorkspaceLayoutAlgorithm { if (stackLayout.mNumFreeformTasks == 0 || task == null) { return false; } - return mTaskIndexMap.containsKey(task.key); + return mTaskRectMap.containsKey(task.key); } /** @@ -95,34 +139,35 @@ public class FreeformWorkspaceLayoutAlgorithm { */ public TaskViewTransform getTransform(Task task, TaskViewTransform transformOut, TaskStackLayoutAlgorithm stackLayout) { - if (mTaskIndexMap.containsKey(task.key)) { + if (mTaskRectMap.containsKey(task.key)) { Rect taskRect = stackLayout.mTaskRect; - int taskIndex = mTaskIndexMap.get(task.key); + RectF ffRect = mTaskRectMap.get(task.key); + float scale = Math.max(ffRect.width() / taskRect.width(), + ffRect.height() / taskRect.height()); int topOffset = (stackLayout.mFreeformRect.top - taskRect.top); - int x = taskIndex % mFreeformCellXCount; - int y = taskIndex / mFreeformCellXCount; + int scaleXOffset = (int) (((1f - scale) * taskRect.width()) / 2); + int scaleYOffset = (int) (((1f - scale) * taskRect.height()) / 2); - Bitmap thumbnail = task.thumbnail; - float thumbnailScale = 1f; - float thumbnailWidth = mFreeformCellWidth; - float thumbnailHeight = mFreeformCellHeight; - if (thumbnail != null) { - int bitmapWidth = task.thumbnail.getWidth(); - int bitmapHeight = task.thumbnail.getHeight(); - thumbnailScale = Math.min((float) mFreeformCellWidth / bitmapWidth, - (float) mFreeformCellHeight / bitmapHeight); - thumbnailWidth = bitmapWidth * thumbnailScale; - thumbnailHeight = bitmapHeight * thumbnailScale; - } - int scaleXOffset = (int) (((1f - thumbnailScale) * thumbnailWidth) / 2); - int scaleYOffset = (int) (((1f - thumbnailScale) * thumbnailHeight) / 2); - transformOut.scale = thumbnailScale * 0.9f; - transformOut.translationX = x * mFreeformCellWidth - scaleXOffset; - transformOut.translationY = topOffset + y * mFreeformCellHeight - scaleYOffset; + transformOut.scale = scale * 0.95f; + transformOut.translationX = (int) (ffRect.left - scaleXOffset); + transformOut.translationY = (int) (topOffset + ffRect.top - scaleYOffset); transformOut.translationZ = stackLayout.mMaxTranslationZ; - transformOut.rect.set(stackLayout.mTaskRect); + transformOut.clipBottom = (int) (taskRect.height() - (ffRect.height() / scale)); + transformOut.clipRight = (int) (taskRect.width() - (ffRect.width() / scale)); + if (task.thumbnail != null) { + transformOut.thumbnailScale = Math.min( + ((float) taskRect.width() - transformOut.clipRight) / + task.thumbnail.getWidth(), + ((float) taskRect.height() - transformOut.clipBottom) / + task.thumbnail.getHeight()); + } else { + transformOut.thumbnailScale = 1f; + } + transformOut.rect.set(taskRect); transformOut.rect.offset(transformOut.translationX, transformOut.translationY); Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale); + transformOut.rect.right -= transformOut.clipRight * scale; + transformOut.rect.bottom -= transformOut.clipBottom * scale; transformOut.visible = true; transformOut.p = 1f; diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java index 5278aa38826c..d9e352dad9e2 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java @@ -334,7 +334,6 @@ public class TaskStackLayoutAlgorithm { * including the search bar. */ public void initialize(Rect taskStackBounds, StackState state) { - SystemServicesProxy ssp = Recents.getSystemServices(); RecentsDebugFlags debugFlags = Recents.getDebugFlags(); RecentsConfiguration config = Recents.getConfiguration(); int widthPadding = (int) (config.taskStackWidthPaddingPct * taskStackBounds.width()); @@ -589,8 +588,15 @@ public class TaskStackLayoutAlgorithm { transformOut.reset(); return transformOut; } - return getStackTransform(mTaskIndexMap.get(task.key), stackScroll, transformOut, + getStackTransform(mTaskIndexMap.get(task.key), stackScroll, transformOut, frontTransform); + if (task.thumbnail != null) { + transformOut.thumbnailScale = (float) mTaskRect.width() / task.thumbnail.getWidth(); + } + if (DEBUG) { + Log.d(TAG, "getTransform: " + task.key + ", " + transformOut); + } + return transformOut; } } @@ -653,6 +659,9 @@ public class TaskStackLayoutAlgorithm { transformOut.rect.offset(transformOut.translationX, transformOut.translationY); Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale); transformOut.visible = true; + transformOut.clipBottom = 0; + transformOut.clipRight = 0; + transformOut.thumbnailScale = 1f; transformOut.p = relP; return transformOut; } 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 5f289c074365..ae6cc46e49cd 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -16,10 +16,6 @@ package com.android.systemui.recents.views; -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.AnimatorSet; -import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.ComponentName; import android.content.Context; @@ -139,11 +135,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // A convenience update listener to request updating clipping of tasks private ValueAnimator.AnimatorUpdateListener mRequestUpdateClippingListener = new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - requestUpdateStackViewsClip(); - } - }; + @Override + public void onAnimationUpdate(ValueAnimator animation) { + requestUpdateStackViewsClip(); + } + }; // The drop targets for a task drag private DropTarget mFreeformWorkspaceDropTarget = new DropTarget() { @@ -474,8 +470,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } // Animate the task into place - tv.updateViewPropertiesToTaskTransform(transform, - mStackViewsAnimationDuration, mRequestUpdateClippingListener); + tv.updateViewPropertiesToTaskTransform(transform, transform.clipBottom, + mStackViewsAnimationDuration, mFastOutSlowInInterpolator, + mRequestUpdateClippingListener); // Reattach it in the right z order detachViewFromParent(tv); @@ -497,7 +494,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } // Pick up all the newly visible children and update all the existing children - for (int i = visibleStackRange[0]; isValidVisibleStackRange && i >= visibleStackRange[1]; i--) { + for (int i = visibleStackRange[0]; + isValidVisibleStackRange && i >= visibleStackRange[1]; i--) { Task task = tasks.get(i); TaskViewTransform transform = mCurrentTaskTransforms.get(i); TaskView tv = mTmpTaskViewMap.get(task); @@ -516,21 +514,25 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal mLayoutAlgorithm.getStackTransform(0f, 0f, mTmpStackBackTransform, null); } - tv.updateViewPropertiesToTaskTransform(mTmpStackBackTransform, 0); + tv.updateViewPropertiesToTaskTransform(mTmpStackBackTransform, 0, 0, + mFastOutSlowInInterpolator, mRequestUpdateClippingListener); } else { if (!hasStackFrontTransform) { hasStackFrontTransform = true; mLayoutAlgorithm.getStackTransform(1f, 0f, mTmpStackFrontTransform, null); } - tv.updateViewPropertiesToTaskTransform(mTmpStackFrontTransform, 0); + tv.updateViewPropertiesToTaskTransform(mTmpStackFrontTransform, 0, 0, + mFastOutSlowInInterpolator, mRequestUpdateClippingListener); } } } - // Animate the task into place + // Animate the task into place, the clip for stack tasks will be calculated in + // clipTaskViews() tv.updateViewPropertiesToTaskTransform(transform, - mStackViewsAnimationDuration, mRequestUpdateClippingListener); + tv.getViewBounds().getClipBottom(), mStackViewsAnimationDuration, + mFastOutSlowInInterpolator, mRequestUpdateClippingListener); } // Update the focus if the previous focused task was returned to the view pool @@ -988,6 +990,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } requestSynchronizeStackViewsWithModel(); synchronizeStackViewsWithModel(); + requestUpdateStackViewsClip(); clipTaskViews(true /* forceUpdate */); } } @@ -1131,8 +1134,15 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } } - public boolean isTransformedTouchPointInView(float x, float y, View child) { - return isTransformedTouchPointInView(x, y, child, null); + public boolean isTransformedTouchPointInView(float x, float y, TaskView tv) { + final float[] point = new float[2]; + point[0] = x; + point[1] = y; + transformPointToViewLocal(point, tv); + x = point[0]; + y = point[1]; + return (0 <= x) && (x < (tv.getMeasuredWidth() - tv.getViewBounds().getClipRight())) && + (0 <= y) && (y < (tv.getMeasuredHeight() - tv.getViewBounds().getClipBottom())); } @Override @@ -1343,9 +1353,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal @Override public void onTaskViewClipStateChanged(TaskView tv) { - if (!mStackViewsDirty) { - invalidate(); - } + requestUpdateStackViewsClip(); } /**** TaskStackViewScroller.TaskStackViewScrollerCallbacks ****/ @@ -1425,12 +1433,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } } - private AnimatorSet mDropAnimation; - public final void onBusEvent(DragStartEvent event) { - // Cancel the existing drop animation - Utilities.cancelAnimationWithoutCallbacks(mDropAnimation); - if (event.task.isFreeformTask()) { // Animate to the front of the stack mStackScroller.animateScroll(mStackScroller.getStackScroll(), @@ -1460,47 +1463,20 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal boolean hasChangedStacks = (!isFreeformTask && event.dropTarget == mFreeformWorkspaceDropTarget) || (isFreeformTask && event.dropTarget == mStackDropTarget); - if (hasChangedStacks) { - ArrayList<Animator> animations = new ArrayList<>(); + event.postAnimationTrigger.increment(); + if (hasChangedStacks) { // Move the task to the right position in the stack (ie. the front of the stack if // freeform or the front of the stack if fullscreen). Note, we MUST move the tasks // before we update their stack ids, otherwise, the keys will have changed. if (event.dropTarget == mFreeformWorkspaceDropTarget) { mStack.moveTaskToStack(event.task, FREEFORM_WORKSPACE_STACK_ID); - updateLayout(true); - - // Update the clipping to match the scaled bitmap rect - TaskViewThumbnail thumbnailView = event.taskView.mThumbnailView; - float thumbnailScale = thumbnailView.computeThumbnailScale(true); - RectF bitmapRect = thumbnailView.getScaledBitmapRect(thumbnailScale); - AnimateableViewBounds viewBounds = event.taskView.getViewBounds(); - int clipRight = (int) (thumbnailView.getMeasuredWidth() - bitmapRect.width()); - int clipBottom = (int) (thumbnailView.getMeasuredHeight() - bitmapRect.height()); - animations.add(ObjectAnimator.ofFloat(thumbnailView, TaskViewThumbnail.BITMAP_SCALE, - thumbnailView.getBitmapScale(), thumbnailScale)); - animations.add(ObjectAnimator.ofInt(viewBounds, AnimateableViewBounds.CLIP_BOTTOM, - viewBounds.getClipBottom(), clipBottom)); - animations.add(ObjectAnimator.ofInt(viewBounds, AnimateableViewBounds.CLIP_RIGHT, - viewBounds.getClipRight(), clipRight)); } else if (event.dropTarget == mStackDropTarget) { mStack.moveTaskToStack(event.task, FULLSCREEN_WORKSPACE_STACK_ID); - updateLayout(true); - - // Reset the clipping when animating to the stack - TaskViewThumbnail thumbnailView = event.taskView.mThumbnailView; - float thumbnailScale = thumbnailView.computeThumbnailScale(false); - AnimateableViewBounds viewBounds = event.taskView.getViewBounds(); - animations.add(ObjectAnimator.ofFloat(thumbnailView, TaskViewThumbnail.BITMAP_SCALE, - thumbnailView.getBitmapScale(), thumbnailScale)); - animations.add(ObjectAnimator.ofInt(viewBounds, AnimateableViewBounds.CLIP_BOTTOM, - viewBounds.getClipBottom(), 0)); - animations.add(ObjectAnimator.ofInt(viewBounds, AnimateableViewBounds.CLIP_RIGHT, - viewBounds.getClipRight(), 0)); } + updateLayout(true); // Move the task to the new stack in the system after the animation completes - event.postAnimationTrigger.increment(); event.postAnimationTrigger.addLastDecrementRunnable(new Runnable() { @Override public void run() { @@ -1508,22 +1484,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal ssp.moveTaskToStack(event.task.key.id, event.task.key.stackId); } }); - - // Animate the normal properties of the view - mDropAnimation = new AnimatorSet(); - mDropAnimation.playTogether(animations); - mDropAnimation.setDuration(250); - mDropAnimation.setInterpolator(mFastOutSlowInInterpolator); - mDropAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - event.postAnimationTrigger.decrement(); - } - }); - mDropAnimation.start(); } - - event.postAnimationTrigger.increment(); event.taskView.animate() .withEndAction(event.postAnimationTrigger.decrementAsRunnable()); 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 f2c89e66f517..6fdfe620fc59 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -18,6 +18,7 @@ package com.android.systemui.recents.views; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; @@ -28,6 +29,7 @@ import android.graphics.Paint; import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; +import android.graphics.Rect; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; @@ -80,6 +82,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, boolean mIsFocusAnimated; boolean mClipViewInStack; AnimateableViewBounds mViewBounds; + private AnimatorSet mClipAnimation; View mContent; TaskViewThumbnail mThumbnailView; @@ -209,23 +212,45 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(heightWithoutPadding, MeasureSpec.EXACTLY)); mThumbnailView.updateClipToTaskBar(mHeaderView); + setMeasuredDimension(width, height); invalidateOutline(); } /** 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) { + void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform, int clipBottom, + int duration, Interpolator interpolator, + ValueAnimator.AnimatorUpdateListener updateCallback) { RecentsConfiguration config = Recents.getConfiguration(); + Utilities.cancelAnimationWithoutCallbacks(mClipAnimation); // Apply the transform - toTransform.applyToTaskView(this, duration, mFastOutSlowInInterpolator, false, + toTransform.applyToTaskView(this, duration, interpolator, false, !config.fakeShadows, updateCallback); + // Update the clipping + if (duration > 0) { + mClipAnimation = new AnimatorSet(); + mClipAnimation.playTogether( + ObjectAnimator.ofInt(mViewBounds, AnimateableViewBounds.CLIP_BOTTOM, + mViewBounds.getClipBottom(), clipBottom), + ObjectAnimator.ofInt(mViewBounds, AnimateableViewBounds.CLIP_RIGHT, + mViewBounds.getClipRight(), toTransform.clipRight), + ObjectAnimator.ofFloat(mThumbnailView, TaskViewThumbnail.BITMAP_SCALE, + mThumbnailView.getBitmapScale(), toTransform.thumbnailScale)); + mClipAnimation.setStartDelay(toTransform.startDelay); + mClipAnimation.setDuration(duration); + mClipAnimation.setInterpolator(interpolator); + mClipAnimation.start(); + } else { + mViewBounds.setClipBottom(clipBottom, false /* forceUpdate */); + mViewBounds.setClipRight(toTransform.clipRight, false /* forceUpdate */); + mThumbnailView.setBitmapScale(toTransform.thumbnailScale); + } + if (!config.useHardwareLayers) { + mThumbnailView.updateThumbnailVisibility(clipBottom - getPaddingBottom()); + } + // Update the task progress Utilities.cancelAnimationWithoutCallbacks(mTaskProgressAnimator); if (duration <= 0) { @@ -673,11 +698,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, @Override public void onTaskDataLoaded() { - SystemServicesProxy ssp = Recents.getSystemServices(); if (mThumbnailView != null && mHeaderView != null) { // Bind each of the views to the new task data mThumbnailView.rebindToTask(mTask); mHeaderView.rebindToTask(mTask); + // Rebind any listeners mActionButtonView.setOnClickListener(this); setOnLongClickListener(this); @@ -721,7 +746,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, @Override public boolean onLongClick(View v) { SystemServicesProxy ssp = Recents.getSystemServices(); - if (v == this && !ssp.hasDockedTask()) { + // Since we are clipping the view to the bounds, manually do the hit test + Rect clipBounds = new Rect(mViewBounds.mClipBounds); + clipBounds.scale(getScaleX()); + boolean inBounds = clipBounds.contains(mDownTouchPos.x, mDownTouchPos.y); + if (v == this && inBounds && !ssp.hasDockedTask()) { // Start listening for drag events setClipViewInStack(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 c288afb87302..7bb2c7bb9fe2 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java @@ -25,7 +25,6 @@ import android.graphics.LightingColorFilter; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; -import android.graphics.RectF; import android.graphics.Shader; import android.util.AttributeSet; import android.util.FloatProperty; @@ -56,15 +55,11 @@ public class TaskViewThumbnail extends View { } }; - private Task mTask; - // Drawing int mCornerRadius; float mDimAlpha; Matrix mScaleMatrix = new Matrix(); Paint mDrawPaint = new Paint(); - RectF mBitmapRect = new RectF(); - RectF mLayoutRect = new RectF(); float mBitmapScale = 1f; BitmapShader mBitmapShader; LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0); @@ -104,15 +99,6 @@ public class TaskViewThumbnail extends View { } @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - if (changed) { - mLayoutRect.set(0, 0, getWidth(), getHeight()); - setBitmapScale(computeThumbnailScale(mTask != null ? mTask.isFreeformTask() : false)); - } - } - - @Override protected void onDraw(Canvas canvas) { if (mInvisible) { return; @@ -129,16 +115,10 @@ public class TaskViewThumbnail extends View { mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mDrawPaint.setShader(mBitmapShader); - mBitmapRect.set(0, 0, bm.getWidth(), bm.getHeight()); } else { mBitmapShader = null; mDrawPaint.setShader(null); } - if (mTask != null) { - setBitmapScale(computeThumbnailScale(mTask != null ? mTask.isFreeformTask() : false)); - } else { - setBitmapScale(1f); - } } /** Updates the paint to draw the thumbnail. */ @@ -160,32 +140,6 @@ public class TaskViewThumbnail extends View { } /** - * Returns the scale to apply to a thumbnail bitmap relative to this view rect. - */ - public float computeThumbnailScale(boolean isFreeformTask) { - if (isFreeformTask) { - // For freeform tasks, we scale the bitmap rect to fit in the layout rect - return Math.min(mLayoutRect.width() / mBitmapRect.width(), - mLayoutRect.height() / mBitmapRect.height()); - } else { - // For stack tasks, we scale the bitmap to fit the width - return Math.max(1f, mLayoutRect.width() / mBitmapRect.width()); - } - } - - /** - * Returns the scaled bitmap rect. - */ - public RectF getScaledBitmapRect(float scale) { - RectF scaledBitmapRect = new RectF(mBitmapRect); - scaledBitmapRect.left *= scale; - scaledBitmapRect.top *= scale; - scaledBitmapRect.right *= scale; - scaledBitmapRect.bottom *= scale; - return scaledBitmapRect; - } - - /** * Sets the scale of the bitmap relative to this view. */ public void setBitmapScale(float scale) { @@ -235,7 +189,6 @@ public class TaskViewThumbnail extends View { /** Binds the thumbnail view to the task */ void rebindToTask(Task t) { - mTask = t; if (t.thumbnail != null) { setThumbnail(t.thumbnail); } else { @@ -245,7 +198,6 @@ public class TaskViewThumbnail extends View { /** Unbinds the thumbnail view from the task */ void unbindFromTask() { - mTask = null; setThumbnail(null); } } 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 6d43f9c570ca..c3e090630d7f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java @@ -18,19 +18,28 @@ package com.android.systemui.recents.views; import android.animation.ValueAnimator; import android.graphics.RectF; -import android.view.View; import android.view.ViewPropertyAnimator; import android.view.animation.Interpolator; /* The transform state for a task view */ public class TaskViewTransform { + + // TODO: Move this out of the transform public int startDelay = 0; + public int translationX = 0; public int translationY = 0; public float translationZ = 0; public float scale = 1f; public float alpha = 1f; + + // Clip and thumbnail scale are untransformed layout-space properties + // The bottom clip is only used for freeform workspace tasks + public int clipBottom = 0; + public int clipRight = 0; + public float thumbnailScale = 1f; + public boolean visible = false; float p = 0f; @@ -42,18 +51,6 @@ public class TaskViewTransform { // Do nothing } - public TaskViewTransform(TaskViewTransform o) { - startDelay = o.startDelay; - translationX = o.translationX; - translationY = o.translationY; - translationZ = o.translationZ; - scale = o.scale; - alpha = o.alpha; - visible = o.visible; - rect.set(o.rect); - p = o.p; - } - /** * Resets the current transform. */ @@ -64,6 +61,9 @@ public class TaskViewTransform { translationZ = 0; scale = 1f; alpha = 1f; + clipBottom = 0; + clipRight = 0; + thumbnailScale = 1f; visible = false; rect.setEmpty(); p = 0f; @@ -87,7 +87,7 @@ public class TaskViewTransform { } /** Applies this transform to a view. */ - public void applyToTaskView(View v, int duration, Interpolator interp, boolean allowLayers, + public void applyToTaskView(TaskView v, int duration, Interpolator interp, boolean allowLayers, boolean allowShadows, ValueAnimator.AnimatorUpdateListener updateCallback) { // Check to see if any properties have changed, and update the task view if (duration > 0) { @@ -149,7 +149,7 @@ public class TaskViewTransform { } /** Reset the transform on a view. */ - public static void reset(View v) { + public static void reset(TaskView v) { // Cancel any running animations v.animate().cancel(); v.setTranslationX(0f); @@ -158,6 +158,9 @@ public class TaskViewTransform { v.setScaleX(1f); v.setScaleY(1f); v.setAlpha(1f); + v.getViewBounds().setClipRight(0, false /* forceUpdate */); + v.getViewBounds().setClipBottom(0, false /* forceUpdate */); + v.mThumbnailView.setBitmapScale(1f); } @Override |