summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/events/EventBus.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java151
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java103
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java47
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java33
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