summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI/src/com/android/systemui/recents
diff options
context:
space:
mode:
authorWinson Chung <winsonc@google.com>2014-07-22 12:27:13 -0700
committerWinson Chung <winsonc@google.com>2014-07-22 22:25:33 +0000
commitdcfa7976fa836ae90bb4a579892a18a0abf35b3c (patch)
tree67a3b17fd0b3f7f93a266ba0c185b5edb6cbd181 /packages/SystemUI/src/com/android/systemui/recents
parent8d7f8a253db1392c74287399207096c9c97c7324 (diff)
downloadframeworks_base-dcfa7976fa836ae90bb4a579892a18a0abf35b3c.zip
frameworks_base-dcfa7976fa836ae90bb4a579892a18a0abf35b3c.tar.gz
frameworks_base-dcfa7976fa836ae90bb4a579892a18a0abf35b3c.tar.bz2
Intermediate refactoring to move towards in-app view transitions.
- Fixing bug where we weren't toggling to the right task when using affiliations - Refactoring task rect calculation to allow full screen task view to be laid out for transitions - Refactoring the view bounds animations into a separate class - Refactoring the footer view (for lock-to-task) out of TaskView - Refactoring some transform code out of TaskView - Removing fullscreen overlay view - Fixing case where extra invalidations and layouts were still happening in FixedSizeImageView - Adding debug overlay to replace specific debug drawing code Change-Id: Ibf98b6a0782a68cd84582203c807cece1ff3379f
Diffstat (limited to 'packages/SystemUI/src/com/android/systemui/recents')
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java111
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/Task.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java118
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/DebugOverlayView.java113
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java285
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java126
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java117
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java244
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java67
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java408
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java72
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java13
18 files changed, 925 insertions, 891 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 66e5d14..591149c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -23,6 +23,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
@@ -70,10 +71,13 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
// Task launching
RecentsConfiguration mConfig;
- Rect mWindowRect;
- Rect mTaskStackBounds;
+ Rect mWindowRect = new Rect();
+ Rect mTaskStackBounds = new Rect();
+ Rect mSystemInsets = new Rect();
TaskViewTransform mTmpTransform = new TaskViewTransform();
int mStatusBarHeight;
+ int mNavBarHeight;
+ int mNavBarWidth;
// Variables to keep track of if we need to start recents after binding
View mStatusBarView;
@@ -81,15 +85,23 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
long mLastToggleTime;
public AlternateRecentsComponent(Context context) {
+ Resources res = context.getResources();
mContext = context;
mSystemServicesProxy = new SystemServicesProxy(context);
mHandler = new Handler();
mConfig = RecentsConfiguration.reinitialize(context, mSystemServicesProxy);
mWindowRect = mSystemServicesProxy.getWindowRect();
mTaskStackBounds = new Rect();
- mConfig.getTaskStackBounds(mWindowRect.width(), mWindowRect.height(), mTaskStackBounds);
- mStatusBarHeight = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
+ mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ mNavBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
+ mNavBarWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
+ mConfig.getTaskStackBounds(mWindowRect.width(), mWindowRect.height(), mStatusBarHeight,
+ mNavBarWidth, mTaskStackBounds);
+ if (mConfig.isLandscape && mConfig.transposeRecentsLayoutWithOrientation) {
+ mSystemInsets.set(0, mStatusBarHeight, mNavBarWidth, 0);
+ } else {
+ mSystemInsets.set(0, mStatusBarHeight, 0, mNavBarHeight);
+ }
}
public void onStart() {
@@ -150,7 +162,13 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
mConfig = RecentsConfiguration.reinitialize(mContext, mSystemServicesProxy);
mConfig.updateOnConfigurationChange();
mWindowRect = mSystemServicesProxy.getWindowRect();
- mConfig.getTaskStackBounds(mWindowRect.width(), mWindowRect.height(), mTaskStackBounds);
+ mConfig.getTaskStackBounds(mWindowRect.width(), mWindowRect.height(), mStatusBarHeight,
+ mNavBarWidth, mTaskStackBounds);
+ if (mConfig.isLandscape && mConfig.transposeRecentsLayoutWithOrientation) {
+ mSystemInsets.set(0, mStatusBarHeight, mNavBarWidth, 0);
+ } else {
+ mSystemInsets.set(0, mStatusBarHeight, 0, mNavBarHeight);
+ }
sLastScreenshot = null;
}
@@ -301,7 +319,9 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
// Get the stack
TaskStackView tsv = new TaskStackView(mContext, stack);
TaskStackViewLayoutAlgorithm algo = tsv.getStackAlgorithm();
- tsv.computeRects(mTaskStackBounds.width(), mTaskStackBounds.height() - mStatusBarHeight, 0, 0);
+ Rect taskStackBounds = new Rect(mTaskStackBounds);
+ taskStackBounds.bottom -= mSystemInsets.bottom;
+ tsv.computeRects(mWindowRect.width(), mWindowRect.height(), taskStackBounds);
tsv.setStackScrollToInitialState();
// Find the running task in the TaskStack
@@ -325,8 +345,6 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
// Get the transform for the running task
mTmpTransform = algo.getStackTransform(task, tsv.getStackScroll(), mTmpTransform);
- mTmpTransform.rect.offset(mTaskStackBounds.left, mTaskStackBounds.top);
- mTmpTransform.rect.offset(0, mStatusBarHeight);
return new Rect(mTmpTransform.rect);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 5741f22..7d69b94 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -32,18 +32,20 @@ import android.os.UserHandle;
import android.util.Pair;
import android.view.KeyEvent;
import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewStub;
+import android.widget.FrameLayout;
import android.widget.Toast;
import com.android.systemui.R;
-import com.android.systemui.recents.misc.Console;
import com.android.systemui.recents.misc.DebugTrigger;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.SpaceNode;
+import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.recents.views.FullscreenTransitionOverlayView;
+import com.android.systemui.recents.views.DebugOverlayView;
import com.android.systemui.recents.views.RecentsView;
import com.android.systemui.recents.views.SystemBarScrimViews;
import com.android.systemui.recents.views.ViewAnimation;
@@ -56,8 +58,7 @@ import java.util.ArrayList;
* The main Recents activity that is started from AlternateRecentsComponent.
*/
public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
- RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks,
- FullscreenTransitionOverlayView.FullScreenTransitionViewCallbacks {
+ RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks {
// Actions and Extras sent from AlternateRecentsComponent
final static String EXTRA_TRIGGERED_FROM_ALT_TAB = "extra_triggered_from_alt_tab";
@@ -73,17 +74,14 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
SystemBarScrimViews mScrimViews;
ViewStub mEmptyViewStub;
View mEmptyView;
- ViewStub mFullscreenOverlayStub;
- FullscreenTransitionOverlayView mFullScreenOverlayView;
+ DebugOverlayView mDebugOverlay;
// Search AppWidget
RecentsAppWidgetHost mAppWidgetHost;
AppWidgetProviderInfo mSearchAppWidgetInfo;
AppWidgetHostView mSearchAppWidgetHostView;
-
// Runnables to finish the Recents activity
- FinishRecentsRunnable mFinishRunnable = new FinishRecentsRunnable();
FinishRecentsRunnable mFinishLaunchHomeRunnable;
/**
@@ -97,10 +95,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
Intent mLaunchIntent;
ActivityOptions mLaunchOpts;
- public FinishRecentsRunnable() {
- // Do nothing
- }
-
/**
* Creates a finish runnable that starts the specified intent, using the given
* ActivityOptions.
@@ -151,8 +145,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
} else if (action.equals(ACTION_START_ENTER_ANIMATION)) {
// Try and start the enter animation (or restart it on configuration changed)
ReferenceCountedTrigger t = new ReferenceCountedTrigger(context, null, null, null);
- mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(
- mFullScreenOverlayView, t));
+ mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
onEnterAnimationTriggered();
}
}
@@ -187,11 +180,12 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
/** Updates the set of recent tasks */
void updateRecentsTasks(Intent launchIntent) {
+ // Load all the tasks
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
SpaceNode root = loader.reload(this, Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
ArrayList<TaskStack> stacks = root.getStacks();
if (!stacks.isEmpty()) {
- mRecentsView.setBSP(root);
+ mRecentsView.setTaskStacks(root.getStacks());
}
// Update the configuration based on the launch intent
@@ -207,6 +201,23 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
mConfig.launchedToTaskId = launchIntent.getIntExtra(
AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_TASK_ID, -1);
+ // Mark the task that is the launch target
+ int taskStackCount = stacks.size();
+ if (mConfig.launchedToTaskId != -1) {
+ for (int i = 0; i < taskStackCount; i++) {
+ TaskStack stack = stacks.get(i);
+ ArrayList<Task> tasks = stack.getTasks();
+ int taskCount = tasks.size();
+ for (int j = 0; j < taskCount; j++) {
+ Task t = tasks.get(j);
+ if (t.key.id == mConfig.launchedToTaskId) {
+ t.isLaunchTarget = true;
+ break;
+ }
+ }
+ }
+ }
+
// Update the top level view's visibilities
if (mConfig.launchedWithNoRecentTasks) {
if (mEmptyView == null) {
@@ -286,9 +297,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
/** Dismisses recents if we are already visible and the intent is to toggle the recents view */
boolean dismissRecentsToFocusedTaskOrHome(boolean checkFilteredStackState) {
if (mVisible) {
- // If we are mid-animation into Recents, reverse the animation now
- if (mFullScreenOverlayView != null &&
- mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) return true;
// If we currently have filtered stacks, then unfilter those first
if (checkFilteredStackState &&
mRecentsView.unfilterFilteredStacks()) return true;
@@ -299,8 +307,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
dismissRecentsToHomeRaw(true);
return true;
}
- // Otherwise, try and return to the first Task in the stack
- if (mRecentsView.launchFirstTask()) return true;
+ // Otherwise, try and return to the Task that Recents was launched from
+ if (mRecentsView.launchPreviousTask()) return true;
// If none of the other cases apply, then just go Home
dismissRecentsToHomeRaw(true);
return true;
@@ -323,9 +331,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
/** Dismisses Recents directly to Home if we currently aren't transitioning. */
boolean dismissRecentsToHome(boolean animated) {
if (mVisible) {
- // If we are mid-animation into Recents, reverse the animation now
- if (mFullScreenOverlayView != null &&
- mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) return true;
// Return to Home
dismissRecentsToHomeRaw(animated);
return true;
@@ -363,8 +368,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mEmptyViewStub = (ViewStub) findViewById(R.id.empty_view_stub);
- mFullscreenOverlayStub = (ViewStub) findViewById(R.id.fullscreen_overlay_stub);
mScrimViews = new SystemBarScrimViews(this, mConfig);
+ inflateDebugOverlay();
// Bind the search app widget when we first start up
bindSearchBarAppWidget();
@@ -390,13 +395,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
e.printStackTrace();
}
- // Prepare the screenshot transition if necessary
- if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
- mFullScreenOverlayView = (FullscreenTransitionOverlayView) mFullscreenOverlayStub.inflate();
- mFullScreenOverlayView.setCallbacks(this);
- mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
- }
-
// Update if we are getting a configuration change
if (savedInstanceState != null) {
mConfig.updateOnConfigurationChange();
@@ -404,6 +402,19 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
}
+ /** Inflates the debug overlay if debug mode is enabled. */
+ void inflateDebugOverlay() {
+ if (mConfig.debugModeEnabled && mDebugOverlay == null) {
+ ViewGroup parent = (ViewGroup) findViewById(android.R.id.content).getRootView();
+ mDebugOverlay = new DebugOverlayView(this);
+ FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT);
+ parent.addView(mDebugOverlay, lp);
+ mRecentsView.setDebugOverlay(mDebugOverlay);
+ }
+ }
+
void onConfigurationChange() {
// Update RecentsConfiguration
mConfig = RecentsConfiguration.reinitialize(this,
@@ -411,8 +422,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Try and start the enter animation (or restart it on configuration changed)
ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
- mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(
- mFullScreenOverlayView, t));
+ mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
onEnterAnimationTriggered();
}
@@ -421,13 +431,13 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
super.onNewIntent(intent);
setIntent(intent);
+ // Clear any debug rects
+ if (mDebugOverlay != null) {
+ mDebugOverlay.clear();
+ }
+
// Update the recent tasks
updateRecentsTasks(intent);
-
- // Prepare the screenshot transition if necessary
- if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
- mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
- }
}
@Override
@@ -531,17 +541,25 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
/** Called when debug mode is triggered */
public void onDebugModeTriggered() {
+
if (mConfig.developerOptionsEnabled) {
SharedPreferences settings = getSharedPreferences(getPackageName(), 0);
if (settings.getBoolean(Constants.Values.App.Key_DebugModeEnabled, false)) {
// Disable the debug mode
settings.edit().remove(Constants.Values.App.Key_DebugModeEnabled).apply();
+ mConfig.debugModeEnabled = false;
+ inflateDebugOverlay();
+ mDebugOverlay.disable();
} else {
// Enable the debug mode
settings.edit().putBoolean(Constants.Values.App.Key_DebugModeEnabled, true).apply();
+ mConfig.debugModeEnabled = true;
+ inflateDebugOverlay();
+ mDebugOverlay.enable();
}
- Toast.makeText(this, "Debug mode (" + Constants.Values.App.DebugModeVersion +
- ") toggled, please restart Recents now", Toast.LENGTH_SHORT).show();
+ Toast.makeText(this, "Debug mode (" + Constants.Values.App.DebugModeVersion + ") " +
+ (mConfig.debugModeEnabled ? "Enabled" : "Disabled") + ", please restart Recents now",
+ Toast.LENGTH_SHORT).show();
}
}
@@ -551,19 +569,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
mScrimViews.startEnterRecentsAnimation();
}
- /**** FullscreenTransitionOverlayView.FullScreenTransitionViewCallbacks Implementation ****/
-
- @Override
- public void onEnterAnimationComplete() {
- // Reset the full screenshot transition view
- if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
- mFullScreenOverlayView.reset();
-
- // Recycle the full screen screenshot
- AlternateRecentsComponent.consumeLastScreenshot();
- }
- }
-
/**** RecentsView.RecentsViewCallbacks Implementation ****/
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index a0cab5c..55711cf0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -309,19 +309,16 @@ public class RecentsConfiguration {
* Returns the task stack bounds in the current orientation. These bounds do not account for
* the system insets.
*/
- public void getTaskStackBounds(int width, int height, Rect taskStackBounds) {
- if (hasSearchBarAppWidget()) {
- Rect searchBarBounds = new Rect();
- getSearchBarBounds(width, height, searchBarBounds);
- if (isLandscape && transposeRecentsLayoutWithOrientation) {
- // In landscape, the search bar appears on the left, so shift the task rect right
- taskStackBounds.set(searchBarBounds.width(), 0, width, height);
- } else {
- // In portrait, the search bar appears on the top, so shift the task rect below
- taskStackBounds.set(0, searchBarBounds.height(), width, height);
- }
+ public void getTaskStackBounds(int windowWidth, int windowHeight, int topInset, int rightInset,
+ Rect taskStackBounds) {
+ Rect searchBarBounds = new Rect();
+ getSearchBarBounds(windowWidth, windowHeight, topInset, searchBarBounds);
+ if (isLandscape && transposeRecentsLayoutWithOrientation) {
+ // In landscape, the search bar appears on the left
+ taskStackBounds.set(searchBarBounds.right, topInset, windowWidth - rightInset, windowHeight);
} else {
- taskStackBounds.set(0, 0, width, height);
+ // In portrait, the search bar appears on the top (which already has the inset)
+ taskStackBounds.set(0, searchBarBounds.bottom, windowWidth, windowHeight);
}
}
@@ -329,19 +326,20 @@ public class RecentsConfiguration {
* Returns the search bar bounds in the current orientation. These bounds do not account for
* the system insets.
*/
- public void getSearchBarBounds(int width, int height, Rect searchBarSpaceBounds) {
+ public void getSearchBarBounds(int windowWidth, int windowHeight, int topInset,
+ Rect searchBarSpaceBounds) {
// Return empty rects if search is not enabled
- if (!Constants.DebugFlags.App.EnableSearchLayout) {
- searchBarSpaceBounds.set(0, 0, 0, 0);
- return;
+ int searchBarSize = searchBarSpaceHeightPx;
+ if (!Constants.DebugFlags.App.EnableSearchLayout || !hasSearchBarAppWidget()) {
+ searchBarSize = 0;
}
if (isLandscape && transposeRecentsLayoutWithOrientation) {
// In landscape, the search bar appears on the left
- searchBarSpaceBounds.set(0, 0, searchBarSpaceHeightPx, height);
+ searchBarSpaceBounds.set(0, topInset, searchBarSize, windowHeight);
} else {
// In portrait, the search bar appears on the top
- searchBarSpaceBounds.set(0, 0, width, searchBarSpaceHeightPx);
+ searchBarSpaceBounds.set(0, topInset, windowWidth, topInset + searchBarSize);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 3b436f0..fb77751 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -38,6 +38,7 @@ import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
@@ -437,7 +438,9 @@ public class SystemServicesProxy {
Rect windowRect = new Rect();
if (mWm == null) return windowRect;
- mWm.getDefaultDisplay().getRectSize(windowRect);
+ Point p = new Point();
+ mWm.getDefaultDisplay().getRealSize(p);
+ windowRect.set(0, 0, p.x, p.y);
return windowRect;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 4cf9235..41874fc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -77,6 +77,7 @@ public class Task {
public TaskKey key;
public TaskGrouping group;
public int taskAffiliation;
+ public boolean isLaunchTarget;
public Drawable applicationIcon;
public Drawable activityIcon;
public String activityLabel;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
new file mode 100644
index 0000000..9076818
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.views;
+
+import android.animation.ObjectAnimator;
+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. */
+public class AnimateableViewBounds extends ViewOutlineProvider {
+
+ RecentsConfiguration mConfig;
+
+ View mSourceView;
+ Rect mClipRect = new Rect();
+ Rect mOutlineClipRect = new Rect();
+ int mCornerRadius;
+
+ ObjectAnimator mClipTopAnimator;
+ ObjectAnimator mClipBottomAnimator;
+
+ public AnimateableViewBounds(View source, int cornerRadius) {
+ mConfig = RecentsConfiguration.getInstance();
+ mSourceView = source;
+ mCornerRadius = cornerRadius;
+ mSourceView.setClipToOutline(true);
+ setClipTop(getClipTop());
+ setClipBottom(getClipBottom());
+ setOutlineClipBottom(getOutlineClipBottom());
+ }
+
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRoundRect(Math.max(mClipRect.left, mOutlineClipRect.left),
+ Math.max(mClipRect.top, mOutlineClipRect.top),
+ mSourceView.getMeasuredWidth() - Math.max(mClipRect.right, mOutlineClipRect.right),
+ mSourceView.getMeasuredHeight() - Math.max(mClipRect.bottom, mOutlineClipRect.bottom),
+ mCornerRadius);
+ }
+
+ /** Animates the top clip. */
+ void animateClipTop(int top, int duration) {
+ if (mClipTopAnimator != null) {
+ mClipTopAnimator.removeAllListeners();
+ mClipTopAnimator.cancel();
+ }
+ mClipTopAnimator = ObjectAnimator.ofInt(this, "clipTop", top);
+ mClipTopAnimator.setDuration(duration);
+ mClipTopAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+ mClipTopAnimator.start();
+ }
+
+ /** Sets the top clip. */
+ public void setClipTop(int top) {
+ if (top != mClipRect.top) {
+ mClipRect.top = top;
+ mSourceView.invalidateOutline();
+ }
+ }
+
+ /** Returns the top clip. */
+ public int getClipTop() {
+ return mClipRect.top;
+ }
+
+ /** Animates the bottom clip. */
+ void animateClipBottom(int bottom, int duration) {
+ if (mClipTopAnimator != null) {
+ mClipTopAnimator.removeAllListeners();
+ mClipTopAnimator.cancel();
+ }
+ mClipTopAnimator = ObjectAnimator.ofInt(this, "clipBottom", bottom);
+ mClipTopAnimator.setDuration(duration);
+ mClipTopAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+ mClipTopAnimator.start();
+ }
+
+ /** Sets the bottom clip. */
+ public void setClipBottom(int bottom) {
+ if (bottom != mClipRect.bottom) {
+ mClipRect.bottom = bottom;
+ mSourceView.invalidateOutline();
+ }
+ }
+
+ /** Returns the bottom clip. */
+ public int getClipBottom() {
+ return mClipRect.bottom;
+ }
+
+ public void setOutlineClipBottom(int bottom) {
+ if (bottom != mOutlineClipRect.bottom) {
+ mOutlineClipRect.bottom = bottom;
+ mSourceView.invalidateOutline();
+ }
+ }
+
+ public int getOutlineClipBottom() {
+ return mOutlineClipRect.bottom;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/DebugOverlayView.java b/packages/SystemUI/src/com/android/systemui/recents/views/DebugOverlayView.java
new file mode 100644
index 0000000..6c90fe3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/DebugOverlayView.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.views;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.Pair;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import java.util.ArrayList;
+
+/**
+ * A full screen overlay layer that allows us to draw views from throughout the system on the top
+ * most layer.
+ */
+public class DebugOverlayView extends FrameLayout {
+
+ final static int sCornerRectSize = 50;
+
+ ArrayList<Pair<Rect, Integer>> mRects = new ArrayList<Pair<Rect, Integer>>();
+ Paint mDebugOutline = new Paint();
+ Paint mTmpPaint = new Paint();
+ boolean mEnabled = true;
+
+ public DebugOverlayView(Context context) {
+ super(context);
+ mDebugOutline.setColor(0xFFff0000);
+ mDebugOutline.setStyle(Paint.Style.STROKE);
+ mDebugOutline.setStrokeWidth(8f);
+ setWillNotDraw(false);
+ }
+
+ /** Enables the debug overlay drawing. */
+ public void enable() {
+ mEnabled = true;
+ invalidate();
+ }
+
+ /** Disables the debug overlay drawing. */
+ public void disable() {
+ mEnabled = false;
+ invalidate();
+ }
+
+ /** Clears all debug rects. */
+ public void clear() {
+ mRects.clear();
+ }
+
+ /** Adds a rect to be drawn. */
+ void addRect(Rect r, int color) {
+ mRects.add(new Pair<Rect, Integer>(r, color));
+ invalidate();
+ }
+
+ /** Adds a view's global rect to be drawn. */
+ void addViewRect(View v, int color) {
+ Rect vr = new Rect();
+ v.getGlobalVisibleRect(vr);
+ mRects.add(new Pair<Rect, Integer>(vr, color));
+ invalidate();
+ }
+
+ /** Adds a rect, relative to a given view to be drawn. */
+ void addRectRelativeToView(View v, Rect r, int color) {
+ Rect vr = new Rect();
+ v.getGlobalVisibleRect(vr);
+ r.offsetTo(vr.left, vr.top);
+ mRects.add(new Pair<Rect, Integer>(r, color));
+ invalidate();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ addRect(new Rect(0, 0, sCornerRectSize, sCornerRectSize), 0xFFff0000);
+ addRect(new Rect(getMeasuredWidth() - sCornerRectSize, getMeasuredHeight() - sCornerRectSize,
+ getMeasuredWidth(), getMeasuredHeight()), 0xFFff0000);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (mEnabled) {
+ // Draw the outline
+ canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mDebugOutline);
+
+ // Draw the rects
+ int numRects = mRects.size();
+ for (int i = 0; i < numRects; i++) {
+ Pair<Rect, Integer> r = mRects.get(i);
+ mTmpPaint.setColor(r.second);
+ canvas.drawRect(r.first, mTmpPaint);
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
index 3adee0e..4b5c0bd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeImageView.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents.views;
import android.content.Context;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
@@ -27,8 +28,6 @@ import android.widget.ImageView;
*/
public class FixedSizeImageView extends ImageView {
- int mFixedWidth;
- int mFixedHeight;
boolean mAllowRelayout = true;
boolean mAllowInvalidate = true;
@@ -49,13 +48,6 @@ public class FixedSizeImageView extends ImageView {
}
@Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- mFixedWidth = getMeasuredWidth();
- mFixedHeight = getMeasuredHeight();
- }
-
- @Override
public void requestLayout() {
if (mAllowRelayout) {
super.requestLayout();
@@ -71,7 +63,9 @@ public class FixedSizeImageView extends ImageView {
@Override
public void setImageDrawable(Drawable drawable) {
- if (drawable == null || (mFixedWidth > 0 && mFixedHeight > 0)) {
+ boolean isNullBitmapDrawable = (drawable instanceof BitmapDrawable) &&
+ (((BitmapDrawable) drawable).getBitmap() == null);
+ if (drawable == null || isNullBitmapDrawable) {
mAllowRelayout = false;
mAllowInvalidate = false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java b/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java
deleted file mode 100644
index 63f59be..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.views;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.animation.AccelerateInterpolator;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import com.android.systemui.R;
-import com.android.systemui.recents.RecentsConfiguration;
-
-
-/**
- * The full screen transition view that gets animated down from the full screen into a task
- * thumbnail view.
- */
-public class FullscreenTransitionOverlayView extends FrameLayout {
-
- /** The FullscreenTransitionOverlayView callbacks */
- public interface FullScreenTransitionViewCallbacks {
- void onEnterAnimationComplete();
- }
-
- RecentsConfiguration mConfig;
-
- FullScreenTransitionViewCallbacks mCb;
-
- ImageView mScreenshotView;
- Rect mClipRect = new Rect();
- Paint mLayerPaint = new Paint();
- PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.MULTIPLY);
-
- int mDim;
- int mMaxDim;
- AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator();
-
- boolean mIsAnimating;
- AnimatorSet mEnterAnimation;
-
- public FullscreenTransitionOverlayView(Context context) {
- super(context);
- }
-
- public FullscreenTransitionOverlayView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public FullscreenTransitionOverlayView(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public FullscreenTransitionOverlayView(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- mConfig = RecentsConfiguration.getInstance();
- mMaxDim = mConfig.taskStackMaxDim;
- setClipTop(getClipTop());
- setClipBottom(getClipBottom());
- setDim(getDim());
- setWillNotDraw(false);
- }
-
- @Override
- protected void onFinishInflate() {
- mScreenshotView = (ImageView) findViewById(R.id.image);
- }
-
- /** Sets the callbacks */
- public void setCallbacks(FullScreenTransitionViewCallbacks cb) {
- mCb = cb;
- }
-
- /** Sets the top clip */
- public void setClipTop(int clip) {
- mClipRect.top = clip;
- setClipBounds(mClipRect);
- }
-
- /** Gets the top clip */
- public int getClipTop() {
- return mClipRect.top;
- }
-
- /** Sets the bottom clip */
- public void setClipBottom(int clip) {
- mClipRect.bottom = clip;
- setClipBounds(mClipRect);
- }
-
- /** Gets the top clip */
- public int getClipBottom() {
- return mClipRect.bottom;
- }
-
- /** Returns the current dim. */
- public void setDim(int dim) {
- mDim = dim;
- /*
- int inverse = 255 - mDim;
- mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse));
- mLayerPaint.setColorFilter(mDimColorFilter);
- setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
- */
- }
-
- /** Returns the current dim. */
- public int getDim() {
- return mDim;
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
- }
-
- @Override
- public boolean hasOverlappingRendering() {
- return false;
- }
-
- /** Prepares the screenshot view for the transition into Recents */
- public void prepareAnimateOnEnterRecents(Bitmap screenshot) {
- if (!mConfig.launchedFromAppWithScreenshot) return;
-
- setClipTop(0);
- setClipBottom(getMeasuredHeight());
- setDim(0);
- setTranslationY(0f);
- setScaleX(1f);
- setScaleY(1f);
- setVisibility(mConfig.launchedFromAppWithScreenshot ? View.VISIBLE : View.INVISIBLE);
- if (screenshot != null) {
- mScreenshotView.setImageBitmap(screenshot);
- } else {
- mScreenshotView.setImageDrawable(null);
- }
- }
-
- /** Resets the transition view */
- public void reset() {
- setVisibility(View.GONE);
- mScreenshotView.setImageDrawable(null);
- }
-
- /** Animates this view as it enters recents */
- public void animateOnEnterRecents(ViewAnimation.TaskViewEnterContext ctx,
- final Runnable postAnimRunnable) {
- // Cancel the current animation
- if (mEnterAnimation != null) {
- mEnterAnimation.removeAllListeners();
- mEnterAnimation.cancel();
- }
-
- // Calculate the bottom clip
- Rect targetTaskRect = ctx.targetTaskTransform.rect;
- float scale = (float) targetTaskRect.width() / getMeasuredWidth();
- float scaleYOffset = ((1f - scale) * getMeasuredHeight()) / 2;
- float scaledTopInset = (int) (scale * mConfig.systemInsets.top);
- int translationY = (int) -scaleYOffset + (int) (mConfig.systemInsets.top - scaledTopInset)
- + targetTaskRect.top;
- int clipBottom = mConfig.systemInsets.top + (int) (targetTaskRect.height() / scale);
-
- // Calculate the dim
- float minScale = TaskStackViewLayoutAlgorithm.StackPeekMinScale;
- float scaleRange = 1f - minScale;
- float dim = (1f - ctx.targetTaskTransform.scale) / scaleRange;
- dim = mDimInterpolator.getInterpolation(Math.min(dim, 1f));
- int toDim = Math.max(0, Math.min(mMaxDim, (int) (dim * 255)));
-
- // Enable the HW Layers on the screenshot view
- mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
-
- // Compose the animation
- mEnterAnimation = new AnimatorSet();
- mEnterAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- post(new Runnable() {
- @Override
- public void run() {
- // Mark that we are no longer animating
- mIsAnimating = false;
- // Disable the HW Layers on this view
- setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
- // Notify any callbacks
- mCb.onEnterAnimationComplete();
- // Run the given post-anim runnable
- postAnimRunnable.run();
- }
- });
- }
- });
- // XXX: Translation y should be negative initially to simulate moving from the top of the screen?
- mEnterAnimation.setStartDelay(0);
- mEnterAnimation.setDuration(475);
- mEnterAnimation.setInterpolator(mConfig.fastOutSlowInInterpolator);
- mEnterAnimation.playTogether(
- // ObjectAnimator.ofInt(this, "clipTop", mConfig.systemInsets.top),
- ObjectAnimator.ofInt(this, "clipBottom", clipBottom),
- ObjectAnimator.ofInt(this, "dim", toDim),
- ObjectAnimator.ofFloat(this, "translationY", translationY),
- ObjectAnimator.ofFloat(this, "scaleX", scale),
- ObjectAnimator.ofFloat(this, "scaleY", scale)
- );
- setClipTop(mConfig.systemInsets.top);
- mEnterAnimation.start();
-
- mIsAnimating = true;
- }
-
- /** Animates this view back out of Recents if we were in the process of animating in. */
- public boolean cancelAnimateOnEnterRecents(final Runnable postAnimRunnable) {
- if (mIsAnimating) {
- // Cancel the current animation
- if (mEnterAnimation != null) {
- mEnterAnimation.removeAllListeners();
- mEnterAnimation.cancel();
- }
-
- // Enable the HW Layers on the screenshot view
- mScreenshotView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
-
- // Compose the animation
- mEnterAnimation = new AnimatorSet();
- mEnterAnimation.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- post(new Runnable() {
- @Override
- public void run() {
- // Mark that we are no longer animating
- mIsAnimating = false;
- // Disable the HW Layers on the screenshot view
- mScreenshotView.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
- // Notify any callbacks
- mCb.onEnterAnimationComplete();
- // Run the given post-anim runnable
- postAnimRunnable.run();
- }
- });
- }
- });
- mEnterAnimation.setDuration(475);
- mEnterAnimation.setInterpolator(mConfig.fastOutSlowInInterpolator);
- mEnterAnimation.playTogether(
- ObjectAnimator.ofInt(this, "clipTop", 0),
- ObjectAnimator.ofInt(this, "clipBottom", getMeasuredHeight()),
- ObjectAnimator.ofInt(this, "dim", 0),
- ObjectAnimator.ofFloat(this, "translationY", 0f),
- ObjectAnimator.ofFloat(this, "scaleX", 1f),
- ObjectAnimator.ofFloat(this, "scaleY", 1f)
- );
- mEnterAnimation.start();
-
- return true;
- }
- return false;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index b6479db..356841f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -24,7 +24,6 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Paint;
import android.graphics.Rect;
import android.net.Uri;
import android.provider.Settings;
@@ -40,7 +39,6 @@ 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.SpaceNode;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
@@ -63,13 +61,10 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
RecentsConfiguration mConfig;
LayoutInflater mInflater;
- Paint mDebugModePaint;
+ DebugOverlayView mDebugOverlay;
- // The space partitioning root of this container
- SpaceNode mBSP;
- // Search bar view
+ ArrayList<TaskStack> mStacks;
View mSearchBar;
- // Recents view callbacks
RecentsViewCallbacks mCb;
public RecentsView(Context context) {
@@ -95,10 +90,13 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
mCb = cb;
}
- /** Set/get the bsp root node */
- public void setBSP(SpaceNode n) {
- mBSP = n;
+ /** Sets the debug overlay */
+ public void setDebugOverlay(DebugOverlayView overlay) {
+ mDebugOverlay = overlay;
+ }
+ /** Set/get the bsp root node */
+ public void setTaskStacks(ArrayList<TaskStack> stacks) {
// Remove all TaskStackViews (but leave the search bar)
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
@@ -109,21 +107,18 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
// Create and add all the stacks for this partition of space.
- ArrayList<TaskStack> stacks = mBSP.getStacks();
- for (TaskStack stack : stacks) {
+ mStacks = stacks;
+ int numStacks = mStacks.size();
+ for (int i = 0; i < numStacks; i++) {
+ TaskStack stack = mStacks.get(i);
TaskStackView stackView = new TaskStackView(getContext(), stack);
stackView.setCallbacks(this);
+ // Enable debug mode drawing
+ if (mConfig.debugModeEnabled) {
+ stackView.setDebugOverlay(mDebugOverlay);
+ }
addView(stackView);
}
-
- // Enable debug mode drawing
- if (mConfig.debugModeEnabled) {
- mDebugModePaint = new Paint();
- mDebugModePaint.setColor(0xFFff0000);
- mDebugModePaint.setStyle(Paint.Style.STROKE);
- mDebugModePaint.setStrokeWidth(5f);
- setWillNotDraw(false);
- }
}
/** Launches the focused task from the first stack if possible */
@@ -150,8 +145,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
return false;
}
- /** Launches the first task from the first stack if possible */
- public boolean launchFirstTask() {
+ /** Launches the task that Recents was launched from, if possible */
+ public boolean launchPreviousTask() {
// Get the first stack view
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
@@ -161,20 +156,17 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
TaskStack stack = stackView.mStack;
ArrayList<Task> tasks = stack.getTasks();
- // Get the first task in the stack
+ // Find the launch task in the stack
if (!tasks.isEmpty()) {
- Task task = tasks.get(tasks.size() - 1);
- TaskView tv = null;
-
- // Try and use the first child task view as the source of the launch animation
- if (stackView.getChildCount() > 0) {
- TaskView stv = (TaskView) stackView.getChildAt(stackView.getChildCount() - 1);
- if (stv.getTask() == task) {
- tv = stv;
+ int taskCount = tasks.size();
+ for (int j = 0; j < taskCount; j++) {
+ if (tasks.get(j).isLaunchTarget) {
+ Task task = tasks.get(j);
+ TaskView tv = stackView.getChildViewForTask(task);
+ onTaskViewClicked(stackView, tv, stack, task, false);
+ return true;
}
}
- onTaskViewClicked(stackView, tv, stack, task, false);
- return true;
}
}
}
@@ -242,35 +234,31 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
// Get the search bar bounds and measure the search bar layout
if (mSearchBar != null) {
Rect searchBarSpaceBounds = new Rect();
- mConfig.getSearchBarBounds(width, height - mConfig.systemInsets.top, searchBarSpaceBounds);
+ mConfig.getSearchBarBounds(width, height, mConfig.systemInsets.top, searchBarSpaceBounds);
mSearchBar.measure(
MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.height(), MeasureSpec.EXACTLY));
}
- // We give the full width of the space, not including the right nav bar insets in landscape,
- // to the stack view, since we want the tasks to render under the search bar in landscape.
- // In addition, we give it the full height, not including the top inset or search bar space,
- // since we want the tasks to render under the navigation buttons in portrait.
Rect taskStackBounds = new Rect();
- mConfig.getTaskStackBounds(width, height, taskStackBounds);
- int childWidth = width - mConfig.systemInsets.right;
- int childHeight = taskStackBounds.height() - mConfig.systemInsets.top;
+ mConfig.getTaskStackBounds(width, height, mConfig.systemInsets.top,
+ mConfig.systemInsets.right, taskStackBounds);
- // Measure each TaskStackView
+ // Measure each TaskStackView with the full width and height of the window since the
+ // transition view is a child of that stack view
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child != mSearchBar && child.getVisibility() != GONE) {
- child.measure(MeasureSpec.makeMeasureSpec(childWidth, widthMode),
- MeasureSpec.makeMeasureSpec(childHeight, heightMode));
+ TaskStackView tsv = (TaskStackView) child;
+ // Set the insets to be the top/left inset + search bounds
+ tsv.setStackInsetRect(taskStackBounds);
+ tsv.measure(widthMeasureSpec, heightMeasureSpec);
}
}
@@ -285,49 +273,30 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
// Get the search bar bounds so that we lay it out
if (mSearchBar != null) {
Rect searchBarSpaceBounds = new Rect();
- mConfig.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(), searchBarSpaceBounds);
- mSearchBar.layout(mConfig.systemInsets.left + searchBarSpaceBounds.left,
- mConfig.systemInsets.top + searchBarSpaceBounds.top,
- mConfig.systemInsets.left + mSearchBar.getMeasuredWidth(),
- mConfig.systemInsets.top + mSearchBar.getMeasuredHeight());
+ mConfig.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
+ mConfig.systemInsets.top, searchBarSpaceBounds);
+ mSearchBar.layout(searchBarSpaceBounds.left, searchBarSpaceBounds.top,
+ searchBarSpaceBounds.right, searchBarSpaceBounds.bottom);
}
- // We offset the stack view by the left inset (if any), but lay it out under the search bar.
- // In addition, we offset our stack views by the top inset and search bar height, but not
- // the bottom insets because we want it to render under the navigation buttons.
- Rect taskStackBounds = new Rect();
- mConfig.getTaskStackBounds(getMeasuredWidth(), getMeasuredHeight(), taskStackBounds);
- left += mConfig.systemInsets.left;
- top += mConfig.systemInsets.top + taskStackBounds.top;
-
- // Layout each child
- // XXX: Based on the space node for that task view
+ // Layout each TaskStackView with the full width and height of the window since the
+ // transition view is a child of that stack view
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child != mSearchBar && child.getVisibility() != GONE) {
- TaskStackView tsv = (TaskStackView) child;
- child.layout(left, top, left + tsv.getMeasuredWidth(), top + tsv.getMeasuredHeight());
+ child.layout(left, top, left + child.getMeasuredWidth(),
+ top + child.getMeasuredHeight());
}
}
}
@Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- // Debug mode drawing
- if (mConfig.debugModeEnabled) {
- canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mDebugModePaint);
- }
- }
-
- @Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
// Update the configuration with the latest system insets and trigger a relayout
mConfig.updateSystemInsets(insets.getSystemWindowInsets());
requestLayout();
-
- return insets.consumeSystemWindowInsets(false, false, false, true);
+ return insets.consumeSystemWindowInsets();
}
/** Notifies each task view of the user interaction. */
@@ -364,11 +333,12 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
/** Unfilters any filtered stacks */
public boolean unfilterFilteredStacks() {
- if (mBSP != null) {
+ if (mStacks != null) {
// Check if there are any filtered stacks and unfilter them before we back out of Recents
boolean stacksUnfiltered = false;
- ArrayList<TaskStack> stacks = mBSP.getStacks();
- for (TaskStack stack : stacks) {
+ int numStacks = mStacks.size();
+ for (int i = 0; i < numStacks; i++) {
+ TaskStack stack = mStacks.get(i);
if (stack.hasFilteredTasks()) {
stack.unfilterTasks();
stacksUnfiltered = true;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
index deb9df3..fbfad5c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -43,8 +43,6 @@ class TaskBarView extends FrameLayout {
RecentsConfiguration mConfig;
- Task mTask;
-
ImageView mDismissButton;
ImageView mApplicationIcon;
TextView mActivityDescription;
@@ -52,6 +50,8 @@ class TaskBarView extends FrameLayout {
Drawable mLightDismissDrawable;
Drawable mDarkDismissDrawable;
+ boolean mIsFullscreen;
+
Paint mLayerPaint = new Paint();
static Paint sHighlightPaint;
@@ -113,11 +113,18 @@ class TaskBarView extends FrameLayout {
@Override
protected void onDraw(Canvas canvas) {
- // Draw the highlight at the top edge (but put the bottom edge just out of view)
- float offset = mConfig.taskViewHighlightPx / 2f;
- float radius = mConfig.taskViewRoundedCornerRadiusPx;
- canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset,
- getMeasuredHeight() + radius, radius, radius, sHighlightPaint);
+ if (!mIsFullscreen) {
+ // Draw the highlight at the top edge (but put the bottom edge just out of view)
+ float offset = mConfig.taskViewHighlightPx / 2f;
+ float radius = mConfig.taskViewRoundedCornerRadiusPx;
+ canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset,
+ getMeasuredHeight() + radius, radius, radius, sHighlightPaint);
+ }
+ }
+
+ /** Sets whether the current task is full screen or not. */
+ void setIsFullscreen(boolean isFullscreen) {
+ mIsFullscreen = isFullscreen;
}
/** Synchronizes this bar view's properties with the task's transform */
@@ -149,7 +156,6 @@ class TaskBarView extends FrameLayout {
/** Binds the bar view to the task */
void rebindToTask(Task t) {
- mTask = t;
// If an activity icon is defined, then we use that as the primary icon to show in the bar,
// otherwise, we fall back to the application icon
if (t.activityIcon != null) {
@@ -170,7 +176,6 @@ class TaskBarView extends FrameLayout {
/** Unbinds the bar view from the task */
void unbindFromTask() {
- mTask = null;
mApplicationIcon.setImageDrawable(null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java
new file mode 100644
index 0000000..95af1c9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.views;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+import com.android.systemui.recents.RecentsConfiguration;
+
+
+/** The task footer view */
+public class TaskFooterView extends FrameLayout {
+
+ interface TaskFooterViewCallbacks {
+ public void onTaskFooterHeightChanged(int height, int maxHeight);
+ }
+
+ RecentsConfiguration mConfig;
+
+ TaskFooterViewCallbacks mCb;
+ int mFooterHeight;
+ int mMaxFooterHeight;
+ ObjectAnimator mFooterAnimator;
+
+ public TaskFooterView(Context context) {
+ this(context, null);
+ }
+
+ public TaskFooterView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public TaskFooterView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public TaskFooterView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mConfig = RecentsConfiguration.getInstance();
+ mMaxFooterHeight = mConfig.taskViewLockToAppButtonHeight;
+ setFooterHeight(getFooterHeight());
+ }
+
+ /** Sets the callbacks for when the footer height changes. */
+ void setCallbacks(TaskFooterViewCallbacks cb) {
+ mCb = cb;
+ mCb.onTaskFooterHeightChanged(mFooterHeight, mMaxFooterHeight);
+ }
+
+ /** Sets the footer height. */
+ public void setFooterHeight(int footerHeight) {
+ if (footerHeight != mFooterHeight) {
+ mFooterHeight = footerHeight;
+ mCb.onTaskFooterHeightChanged(footerHeight, mMaxFooterHeight);
+ }
+ }
+
+ /** Gets the footer height. */
+ public int getFooterHeight() {
+ return mFooterHeight;
+ }
+
+ /** Animates the footer into and out of view. */
+ void animateFooterVisibility(final boolean visible, int duration) {
+ // Return early if there is no footer
+ if (mMaxFooterHeight <= 0) return;
+ // Return early if we are already in the final state
+ if (!visible && getVisibility() != View.VISIBLE) return;
+ if (visible && getVisibility() == View.VISIBLE) return;
+
+ // Cancel the previous animation
+ if (mFooterAnimator != null) {
+ mFooterAnimator.removeAllListeners();
+ mFooterAnimator.cancel();
+ }
+ int finalHeight = visible ? mMaxFooterHeight : 0;
+ if (duration > 0) {
+ // Make the view visible for the animation
+ if (visible && getVisibility() != View.VISIBLE) {
+ setVisibility(View.VISIBLE);
+ }
+ mFooterAnimator = ObjectAnimator.ofInt(this, "footerHeight", finalHeight);
+ mFooterAnimator.setDuration(duration);
+ mFooterAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+ mFooterAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (!visible) {
+ setVisibility(View.INVISIBLE);
+ }
+ }
+ });
+ mFooterAnimator.start();
+ } else {
+ setFooterHeight(finalHeight);
+ setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+ }
+ }
+}
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 8b86258..d84a40f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -23,7 +23,6 @@ import android.animation.ValueAnimator;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Canvas;
-import android.graphics.Paint;
import android.graphics.Rect;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -73,6 +72,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
ViewPool<TaskView, Task> mViewPool;
ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<TaskViewTransform>();
DozeTrigger mUIDozeTrigger;
+ DebugOverlayView mDebugOverlay;
+ Rect mTaskStackBounds = new Rect();
// The virtual stack scroll that we use for the card layout
int mStackScroll;
@@ -94,8 +95,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int[] mTmpVisibleRange = new int[2];
Rect mTmpRect = new Rect();
Rect mTmpRect2 = new Rect();
+ TaskViewTransform mTmpTransform = new TaskViewTransform();
+ HashMap<Task, TaskView> mTmpTaskViewMap = new HashMap<Task, TaskView>();
LayoutInflater mInflater;
+ // A convenience runnable to return all views to the pool
+ // XXX: After this is set, we should mark this task stack view as disabled and check that in synchronize model
Runnable mReturnAllViewsToPoolRunnable = new Runnable() {
@Override
public void run() {
@@ -162,6 +167,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mCb = cb;
}
+ /** Sets the debug overlay */
+ public void setDebugOverlay(DebugOverlayView overlay) {
+ mDebugOverlay = overlay;
+ }
+
/** Requests that the views be synchronized with the model */
void requestSynchronizeStackViewsWithModel() {
requestSynchronizeStackViewsWithModel(0);
@@ -179,19 +189,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
- /** Returns a mapping of child view to Task. */
- HashMap<Task, TaskView> getTaskChildViewMap() {
- HashMap<Task, TaskView> taskViewMap = new HashMap<Task, TaskView>();
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- TaskView tv = (TaskView) getChildAt(i);
- taskViewMap.put(tv.getTask(), tv);
- }
- return taskViewMap;
- }
-
/** Finds the child view given a specific task. */
- TaskView getChildViewForTask(Task t) {
+ public TaskView getChildViewForTask(Task t) {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
TaskView tv = (TaskView) getChildAt(i);
@@ -210,19 +209,23 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/**
* Gets the stack transforms of a list of tasks, and returns the visible range of tasks.
*/
- private void updateStackTransforms(ArrayList<TaskViewTransform> taskTransforms,
+ private boolean updateStackTransforms(ArrayList<TaskViewTransform> taskTransforms,
ArrayList<Task> tasks,
int stackScroll,
int[] visibleRangeOut,
boolean boundTranslationsToRect) {
- // XXX: We should be intelligent about where to look for the visible stack range using the
+ // XXX: We should be intelligent about wheee to look for the visible stack range using the
// current stack scroll.
+ // XXX: We should log extra cases like the ones below where we don't expect to hit very often
+ // XXX: Print out approximately how many indices we have to go through to find the first visible transform
int taskTransformCount = taskTransforms.size();
int taskCount = tasks.size();
int frontMostVisibleIndex = -1;
int backMostVisibleIndex = -1;
+
+
// We can reuse the task transforms where possible to reduce object allocation
if (taskTransformCount < taskCount) {
// If there are less transforms than tasks, then add as many transforms as necessary
@@ -256,13 +259,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
if (boundTranslationsToRect) {
transform.translationY = Math.min(transform.translationY,
- mStackAlgorithm.mRect.bottom);
+ mStackAlgorithm.mViewRect.bottom);
}
}
if (visibleRangeOut != null) {
visibleRangeOut[0] = frontMostVisibleIndex;
visibleRangeOut[1] = backMostVisibleIndex;
}
+ return frontMostVisibleIndex != -1 && backMostVisibleIndex != -1;
}
/**
@@ -280,34 +284,33 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
/** Synchronizes the views with the model */
- void synchronizeStackViewsWithModel() {
+ boolean synchronizeStackViewsWithModel() {
if (mStackViewsDirty) {
// Get all the task transforms
ArrayList<Task> tasks = mStack.getTasks();
int stackScroll = getStackScroll();
int[] visibleRange = mTmpVisibleRange;
- updateStackTransforms(mCurrentTaskTransforms, tasks, stackScroll, visibleRange, false);
- TaskViewTransform tmpTransform = new TaskViewTransform();
+ boolean isValidVisibleRange = updateStackTransforms(mCurrentTaskTransforms, tasks, stackScroll, visibleRange, false);
// Return all the invisible children to the pool
- HashMap<Task, TaskView> taskChildViewMap = getTaskChildViewMap();
+ mTmpTaskViewMap.clear();
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
TaskView tv = (TaskView) getChildAt(i);
Task task = tv.getTask();
int taskIndex = mStack.indexOfTask(task);
- if (taskIndex < visibleRange[1] || taskIndex > visibleRange[0]) {
- taskChildViewMap.remove(task);
+ if (visibleRange[1] <= taskIndex && taskIndex <= visibleRange[0]) {
+ mTmpTaskViewMap.put(task, tv);
+ } else {
mViewPool.returnViewToPool(tv);
}
}
// Pick up all the newly visible children and update all the existing children
- boolean isValidVisibleRange = visibleRange[0] != -1 && visibleRange[1] != -1;
for (int i = visibleRange[0]; isValidVisibleRange && i >= visibleRange[1]; i--) {
Task task = tasks.get(i);
TaskViewTransform transform = mCurrentTaskTransforms.get(i);
- TaskView tv = taskChildViewMap.get(task);
+ TaskView tv = mTmpTaskViewMap.get(task);
int taskIndex = mStack.indexOfTask(task);
if (tv == null) {
@@ -316,23 +319,26 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// For items in the list, put them in start animating them from the
// approriate ends of the list where they are expected to appear
if (transform.t < 0) {
- tmpTransform = mStackAlgorithm.getStackTransform(tasks.get(0), stackScroll, tmpTransform);
+ mTmpTransform = mStackAlgorithm.getStackTransform(tasks.get(0), stackScroll, mTmpTransform);
} else {
- tmpTransform = mStackAlgorithm.getStackTransform(tasks.get(Math.min(tasks.size() - 1, visibleRange[0] + 1)),
- stackScroll, tmpTransform);
+ mTmpTransform = mStackAlgorithm.getStackTransform(tasks.get(Math.min(tasks.size() - 1, visibleRange[0] + 1)),
+ stackScroll, mTmpTransform);
}
- tv.updateViewPropertiesToTaskTransform(tmpTransform, 0);
+ tv.updateViewPropertiesToTaskTransform(mTmpTransform, 0);
}
}
- // Update and animate the task into place
+ // Animate the task into place
tv.updateViewPropertiesToTaskTransform(mCurrentTaskTransforms.get(taskIndex),
mStackViewsAnimationDuration);
}
+ // Reset the request-synchronize params
mStackViewsAnimationDuration = 0;
mStackViewsDirty = false;
+ return true;
}
+ return false;
}
/** Updates the clip for each of the task views. */
@@ -368,13 +374,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
clipBottom = (mTmpRect.bottom - scaledMaxFooterHeight - mTmpRect2.top);
}
}
- tv.setClipFromBottom(clipBottom);
+ tv.getViewBounds().setClipBottom(clipBottom);
+ }
+ if (getChildCount() > 0) {
+ // The front most task should never be clipped
+ TaskView tv = (TaskView) getChildAt(getChildCount() - 1);
+ tv.getViewBounds().setClipBottom(0);
}
- }
- if (getChildCount() > 0) {
- // The front most task should never be clipped
- TaskView tv = (TaskView) getChildAt(getChildCount() - 1);
- tv.setClipFromBottom(0);
}
}
@@ -384,18 +390,24 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
TaskView tv = (TaskView) getChildAt(i);
- tv.setClipFromBottom(0);
+ tv.getViewBounds().setClipBottom(0);
}
}
mEnableStackClipping = stackClippingEnabled;
}
+ /** The stack insets to apply to the stack contents */
+ public void setStackInsetRect(Rect r) {
+ mTaskStackBounds.set(r);
+ }
+
/** Sets the current stack scroll */
public void setStackScroll(int value) {
mStackScroll = value;
mUIDozeTrigger.poke();
requestSynchronizeStackViewsWithModel();
}
+
/** Sets the current stack scroll without synchronizing the stack view with the model */
public void setStackScrollRaw(int value) {
mStackScroll = value;
@@ -408,7 +420,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/** Computes the initial stack scroll for the stack. */
int getInitialStackScroll() {
if (mStack.getTaskCount() > 2) {
- return mMaxScroll - (int) (mStackAlgorithm.mTaskRect.height() * (3f/4f));
+ return Math.max(mMinScroll, mMaxScroll - (int) (mStackAlgorithm.mTaskRect.height() * (3f/4f)));
}
return mMaxScroll;
}
@@ -521,7 +533,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/** Returns whether the specified scroll is out of bounds */
boolean isScrollOutOfBounds() {
- return getScrollAmountOutOfBounds(getStackScroll()) != 0;
+ return getScrollAmountOutOfBounds(mStackScroll) != 0;
}
/** Updates the min and max virtual scroll bounds */
@@ -639,24 +651,24 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
@Override
public void dispatchDraw(Canvas canvas) {
- synchronizeStackViewsWithModel();
- clipTaskViews();
+ if (synchronizeStackViewsWithModel()) {
+ clipTaskViews();
+ }
super.dispatchDraw(canvas);
}
/** Computes the stack and task rects */
- public void computeRects(int width, int height, int insetLeft, int insetBottom) {
+ public void computeRects(int windowWidth, int windowHeight, Rect taskStackBounds) {
// Compute the rects in the stack algorithm
- mStackAlgorithm.computeRects(mStack.getTasks(), width, height, insetLeft, insetBottom);
+ mStackAlgorithm.computeRects(mStack.getTasks(), windowWidth, windowHeight, taskStackBounds);
// Update the scroll bounds
updateMinMaxScroll(false);
}
/**
- * This is called with the size of the space not including the top or right insets, or the
- * search bar height in portrait (but including the search bar width in landscape, since we want
- * to draw under it.
+ * This is called with the full window width and height to allow stack view children to
+ * perform the full screen transition down.
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
@@ -664,25 +676,43 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int height = MeasureSpec.getSize(heightMeasureSpec);
// Compute our stack/task rects
- Rect taskStackBounds = new Rect();
- mConfig.getTaskStackBounds(width, height, taskStackBounds);
- computeRects(width, height, taskStackBounds.left, mConfig.systemInsets.bottom);
+ Rect taskStackBounds = new Rect(mTaskStackBounds);
+ taskStackBounds.bottom -= mConfig.systemInsets.bottom;
+ computeRects(width, height, taskStackBounds);
// If this is the first layout, then scroll to the front of the stack and synchronize the
- // stack views immediately
+ // stack views immediately to load all the views
if (mAwaitingFirstLayout) {
setStackScrollToInitialState();
requestSynchronizeStackViewsWithModel();
synchronizeStackViewsWithModel();
+
+ // Find the first task and mark it as full screen
+ if (mConfig.launchedFromAppWithScreenshot) {
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ TaskView tv = (TaskView) getChildAt(i);
+ if (tv.getTask().isLaunchTarget) {
+ tv.setIsFullScreen(true);
+ break;
+ }
+ }
+ }
}
- // Measure each of the children
+ // Measure each of the TaskViews
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
- TaskView t = (TaskView) getChildAt(i);
- t.measure(MeasureSpec.makeMeasureSpec(mStackAlgorithm.mTaskRect.width(), MeasureSpec.EXACTLY),
+ TaskView tv = (TaskView) getChildAt(i);
+ if (tv.isFullScreenView()) {
+ tv.measure(widthMeasureSpec, heightMeasureSpec);
+ } else {
+ tv.measure(
+ MeasureSpec.makeMeasureSpec(mStackAlgorithm.mTaskRect.width(),
+ MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mStackAlgorithm.mTaskRect.height() +
- t.getMaxFooterHeight(), MeasureSpec.EXACTLY));
+ tv.getMaxFooterHeight(), MeasureSpec.EXACTLY));
+ }
}
setMeasuredDimension(width, height);
@@ -698,54 +728,45 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Layout each of the children
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
- TaskView t = (TaskView) getChildAt(i);
- t.layout(mStackAlgorithm.mTaskRect.left, mStackAlgorithm.mStackRectSansPeek.top,
- mStackAlgorithm.mTaskRect.right, mStackAlgorithm.mStackRectSansPeek.top +
- mStackAlgorithm.mTaskRect.height() + t.getMaxFooterHeight());
+ TaskView tv = (TaskView) getChildAt(i);
+ if (tv.isFullScreenView()) {
+ tv.layout(left, top, left + tv.getMeasuredWidth(), top + tv.getMeasuredHeight());
+ } else {
+ tv.layout(mStackAlgorithm.mTaskRect.left, mStackAlgorithm.mTaskRect.top,
+ mStackAlgorithm.mTaskRect.right, mStackAlgorithm.mTaskRect.bottom +
+ tv.getMaxFooterHeight());
+ }
}
if (mAwaitingFirstLayout) {
- // Mark that we have completely the first layout
mAwaitingFirstLayout = false;
+ onFirstLayout();
+ }
+ }
- // Find the target task with the specified id
- ArrayList<Task> tasks = mStack.getTasks();
- Task targetTask = null;
- int targetTaskId = mConfig.launchedToTaskId;
- if (targetTaskId != -1) {
- int taskCount = tasks.size();
- for (int i = 0; i < taskCount; i++) {
- Task t = tasks.get(i);
- if (t.key.id == targetTaskId) {
- targetTask = t;
- break;
- }
- }
- }
-
- // Prepare the first view for its enter animation
- int offsetTopAlign = -mStackAlgorithm.mTaskRect.top;
- int offscreenY = mStackAlgorithm.mRect.bottom -
- (mStackAlgorithm.mTaskRect.top - mStackAlgorithm.mRect.top);
- for (int i = childCount - 1; i >= 0; i--) {
- TaskView tv = (TaskView) getChildAt(i);
- tv.prepareEnterRecentsAnimation(tv.getTask() == targetTask, offsetTopAlign,
- offscreenY);
- }
+ /** Handler for the first layout. */
+ void onFirstLayout() {
+ // Prepare the first view for its enter animation
+ int offscreenY = mStackAlgorithm.mViewRect.bottom -
+ (mStackAlgorithm.mTaskRect.top - mStackAlgorithm.mViewRect.top);
+ int childCount = getChildCount();
+ for (int i = childCount - 1; i >= 0; i--) {
+ TaskView tv = (TaskView) getChildAt(i);
+ tv.prepareEnterRecentsAnimation(tv.getTask().isLaunchTarget, offscreenY);
+ }
- // If the enter animation started already and we haven't completed a layout yet, do the
- // enter animation now
- if (mStartEnterAnimationRequestedAfterLayout) {
- startEnterRecentsAnimation(mStartEnterAnimationContext);
- mStartEnterAnimationRequestedAfterLayout = false;
- mStartEnterAnimationContext = null;
- }
+ // If the enter animation started already and we haven't completed a layout yet, do the
+ // enter animation now
+ if (mStartEnterAnimationRequestedAfterLayout) {
+ startEnterRecentsAnimation(mStartEnterAnimationContext);
+ mStartEnterAnimationRequestedAfterLayout = false;
+ mStartEnterAnimationContext = null;
+ }
- // Update the focused task index to be the next item to the top task
- if (mConfig.launchedWithAltTab) {
- // When alt-tabbing, we focus the next previous task
- focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
- }
+ // Update the focused task index to be the next item to the top task
+ if (mConfig.launchedWithAltTab) {
+ // When alt-tabbing, we focus the next previous task
+ focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
}
}
@@ -759,30 +780,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
if (mStack.getTaskCount() > 0) {
- // Find the target task with the specified id
- ArrayList<Task> tasks = mStack.getTasks();
- Task targetTask = null;
- int targetTaskId = mConfig.launchedToTaskId;
- if (targetTaskId != -1) {
- int taskCount = tasks.size();
- for (int i = 0; i < taskCount; i++) {
- Task t = tasks.get(i);
- if (t.key.id == targetTaskId) {
- targetTask = t;
- break;
- }
- }
- }
-
- // Find the transform for the target task
- if (targetTask != null) {
- ctx.targetTaskTransform = new TaskViewTransform();
- mStackAlgorithm.getStackTransform(targetTask, getStackScroll(), ctx.targetTaskTransform);
- Rect taskStackBounds = new Rect();
- mConfig.getTaskStackBounds(getMeasuredWidth(), getMeasuredHeight(), taskStackBounds);
- ctx.targetTaskTransform.rect.offset(taskStackBounds.left, taskStackBounds.top);
- }
-
// Animate all the task views into view
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
@@ -791,7 +788,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
ctx.currentTaskTransform = new TaskViewTransform();
ctx.currentStackViewIndex = i;
ctx.currentStackViewCount = childCount;
- ctx.isCurrentTaskLaunchTarget = (task == targetTask);
+ ctx.currentTaskRect = mStackAlgorithm.mTaskRect;
mStackAlgorithm.getStackTransform(task, getStackScroll(), ctx.currentTaskTransform);
tv.startEnterRecentsAnimation(ctx);
}
@@ -802,6 +799,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
public void run() {
// Start dozing
mUIDozeTrigger.startDozing();
+ // Request an update of the task views after the animation in to
+ // relayout the fullscreen view back to its normal size
+ if (mConfig.launchedFromAppWithScreenshot) {
+ requestSynchronizeStackViewsWithModel();
+ }
}
});
}
@@ -810,8 +812,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/** Requests this task stacks to start it's exit-recents animation. */
public void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
// Animate all the task views into view
- ctx.offscreenTranslationY = mStackAlgorithm.mRect.bottom -
- (mStackAlgorithm.mTaskRect.top - mStackAlgorithm.mRect.top);
+ ctx.offscreenTranslationY = mStackAlgorithm.mViewRect.bottom -
+ (mStackAlgorithm.mTaskRect.top - mStackAlgorithm.mViewRect.top);
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
TaskView tv = (TaskView) getChildAt(i);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index 65407a6..3c89cd7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -17,7 +17,6 @@
package com.android.systemui.recents.views;
import android.graphics.Rect;
-import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
@@ -30,14 +29,14 @@ public class TaskStackViewLayoutAlgorithm {
// These are all going to change
static final float StackOverlapPct = 0.65f; // The overlap height relative to the task height
- static final float StackPeekHeightPct = 0.1f; // The height of the peek space relative to the stack height
+ static final float StackPeekHeightPct = 0.075f; // The height of the peek space relative to the stack height
static final float StackPeekMinScale = 0.8f; // The min scale of the last card in the peek area
static final int StackPeekNumCards = 3; // The number of cards we see in the peek space
RecentsConfiguration mConfig;
// The various rects that define the stack view
- Rect mRect = new Rect();
+ Rect mViewRect = new Rect();
Rect mStackRect = new Rect();
Rect mStackRectSansPeek = new Rect();
Rect mTaskRect = new Rect();
@@ -53,29 +52,21 @@ public class TaskStackViewLayoutAlgorithm {
}
/** Computes the stack and task rects */
- public void computeRects(ArrayList<Task> tasks, int width, int height, int insetLeft, int insetBottom) {
+ public void computeRects(ArrayList<Task> tasks, int windowWidth, int windowHeight,
+ Rect taskStackBounds) {
// Note: We let the stack view be the full height because we want the cards to go under the
// navigation bar if possible. However, the stack rects which we use to calculate
// max scroll, etc. need to take the nav bar into account
// Compute the stack rects
- mRect.set(0, 0, width, height);
- mStackRect.set(mRect);
- mStackRect.left += insetLeft;
- mStackRect.bottom -= insetBottom;
+ mViewRect.set(0, 0, windowWidth, windowHeight);
+ mStackRect.set(taskStackBounds);
int widthPadding = (int) (mConfig.taskStackWidthPaddingPct * mStackRect.width());
int heightPadding = mConfig.taskStackTopPaddingPx;
- if (Constants.DebugFlags.App.EnableSearchLayout) {
- mStackRect.top += heightPadding;
- mStackRect.left += widthPadding;
- mStackRect.right -= widthPadding;
- mStackRect.bottom -= heightPadding;
- } else {
- mStackRect.inset(widthPadding, heightPadding);
- }
+ mStackRect.inset(widthPadding, heightPadding);
mStackRectSansPeek.set(mStackRect);
- mStackRectSansPeek.top += StackPeekHeightPct * mStackRect.height();
+ mStackRectSansPeek.top += StackPeekHeightPct * windowHeight;
// Compute the task rect
int size = mStackRect.width();
@@ -91,7 +82,7 @@ public class TaskStackViewLayoutAlgorithm {
// Compute the min and max scroll values
int numTasks = Math.max(1, tasks.size());
int taskHeight = mTaskRect.height();
- int stackHeight = mStackRectSansPeek.height();
+ int stackHeight = mStackRect.height();
if (numTasks <= 1) {
// If there is only one task, then center the task in the stack rect (sans peek)
@@ -156,7 +147,7 @@ public class TaskStackViewLayoutAlgorithm {
} else {
transformOut.rect.offset(0, transformOut.translationY);
Utilities.scaleRectAboutCenter(transformOut.rect, transformOut.scale);
- transformOut.visible = Rect.intersects(mRect, transformOut.rect);
+ transformOut.visible = Rect.intersects(mViewRect, transformOut.rect);
}
transformOut.t = t;
return transformOut;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
index 08a25f1..1116d51 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
@@ -17,7 +17,7 @@
package com.android.systemui.recents.views;
import android.content.Context;
-import android.graphics.Canvas;
+import android.graphics.Bitmap;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
@@ -27,11 +27,8 @@ import com.android.systemui.recents.model.Task;
/** The task thumbnail view */
public class TaskThumbnailView extends FixedSizeImageView {
- Task mTask;
-
// Task bar clipping
- Rect mClipRect;
- boolean mClipTaskBar = true;
+ Rect mClipRect = new Rect();
public TaskThumbnailView(Context context) {
this(context, null);
@@ -50,40 +47,51 @@ public class TaskThumbnailView extends FixedSizeImageView {
setScaleType(ScaleType.FIT_XY);
}
- @Override
- public void draw(Canvas canvas) {
- if (mClipTaskBar && (mClipRect != null)) {
- int restoreCount = canvas.save(Canvas.CLIP_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
- canvas.clipRect(mClipRect);
- super.draw(canvas);
- canvas.restoreToCount(restoreCount);
- } else {
- super.draw(canvas);
- }
+ /** Updates the clip rect based on the given task bar. */
+ void enableTaskBarClip(View taskBar) {
+ int top = (int) Math.max(0, taskBar.getTranslationY() +
+ taskBar.getMeasuredHeight() - 1);
+ mClipRect.set(0, top, getMeasuredWidth(), getMeasuredHeight());
+ setClipBounds(mClipRect);
}
- /** Updates the clip rect based on the given task bar. */
- void updateTaskBarClip(View taskBar) {
- // If mClipTaskBar is unset first, then we don't bother setting mTaskBar
- if (mClipTaskBar) {
- int top = (int) Math.max(0, taskBar.getTranslationY() +
- taskBar.getMeasuredHeight() - 1);
- mClipRect = new Rect(0, top, getMeasuredWidth(), getMeasuredHeight());
- invalidate(0, 0, taskBar.getMeasuredWidth(), taskBar.getMeasuredHeight() + 1);
- }
+ /** Convenience method to enable task bar clipping as a runnable. */
+ Runnable enableTaskBarClipAsRunnable(final View taskBar) {
+ return new Runnable() {
+ @Override
+ public void run() {
+ enableTaskBarClip(taskBar);
+ }
+ };
}
/** Disables the task bar clipping. */
- void disableClipTaskBarView() {
- mClipTaskBar = false;
- if (mClipRect != null) {
- invalidate(0, 0, mClipRect.width(), mClipRect.top);
+ Runnable disableTaskBarClipAsRunnable() {
+ return new Runnable() {
+ @Override
+ public void run() {
+ mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight());
+ setClipBounds(mClipRect);
+ }
+ };
+ }
+
+ /** Binds the thumbnail view to the screenshot. */
+ boolean bindToScreenshot(Bitmap ss) {
+ if (ss != null) {
+ setImageBitmap(ss);
+ return true;
}
+ return false;
+ }
+
+ /** Unbinds the thumbnail view from the screenshot. */
+ void unbindFromScreenshot() {
+ setImageBitmap(null);
}
/** Binds the thumbnail view to the task */
void rebindToTask(Task t) {
- mTask = t;
if (t.thumbnail != null) {
setImageBitmap(t.thumbnail);
}
@@ -91,7 +99,6 @@ public class TaskThumbnailView extends FixedSizeImageView {
/** Unbinds the thumbnail view from the task */
void unbindFromTask() {
- mTask = null;
setImageDrawable(null);
}
}
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 4757c5f..d1b33f3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -22,24 +22,23 @@ import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
-import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
-import android.view.ViewOutlineProvider;
-import android.view.ViewPropertyAnimator;
import android.view.animation.AccelerateInterpolator;
import android.widget.FrameLayout;
import com.android.systemui.R;
+import com.android.systemui.recents.AlternateRecentsComponent;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.model.Task;
+// XXX: In debug mode, we should override invalidate() and check the layout type (do this in TaskStackView as well)
/* A task view */
-public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.OnClickListener,
- View.OnLongClickListener {
+public class TaskView extends FrameLayout implements Task.TaskCallbacks,
+ TaskFooterView.TaskFooterViewCallbacks, View.OnClickListener, View.OnLongClickListener {
/** The TaskView callbacks */
interface TaskViewCallbacks {
public void onTaskViewAppIconClicked(TaskView tv);
@@ -51,10 +50,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
RecentsConfiguration mConfig;
- int mFooterHeight;
- int mMaxFooterHeight;
- ObjectAnimator mFooterAnimator;
-
int mDim;
int mMaxDim;
AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator();
@@ -62,14 +57,15 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
Task mTask;
boolean mTaskDataLoaded;
boolean mIsFocused;
+ boolean mIsFullScreenView;
boolean mIsStub;
boolean mClipViewInStack;
- int mClipFromBottom;
+ AnimateableViewBounds mViewBounds;
Paint mLayerPaint = new Paint();
TaskThumbnailView mThumbnailView;
TaskBarView mBarView;
- View mLockToAppButtonView;
+ TaskFooterView mFooterView;
TaskViewCallbacks mCb;
// Optimizations
@@ -80,18 +76,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
updateDimOverlayFromScale();
}
};
- Runnable mEnableThumbnailClip = new Runnable() {
- @Override
- public void run() {
- mThumbnailView.updateTaskBarClip(mBarView);
- }
- };
- Runnable mDisableThumbnailClip = new Runnable() {
- @Override
- public void run() {
- mThumbnailView.disableClipTaskBarView();
- }
- };
public TaskView(Context context) {
@@ -109,38 +93,36 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
public TaskView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mConfig = RecentsConfiguration.getInstance();
- mMaxFooterHeight = mConfig.taskViewLockToAppButtonHeight;
+ mMaxDim = mConfig.taskStackMaxDim;
+ mClipViewInStack = true;
+ mViewBounds = new AnimateableViewBounds(this, mConfig.taskViewRoundedCornerRadiusPx);
setWillNotDraw(false);
- setClipToOutline(true);
setDim(getDim());
- setFooterHeight(getFooterHeight());
- setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- // The current height is measured with the footer, so account for the footer height
- // and the current clip (in the stack)
- int height = getMeasuredHeight() - mClipFromBottom - mMaxFooterHeight + mFooterHeight;
- outline.setRoundRect(0, 0, getWidth(), height,
- mConfig.taskViewRoundedCornerRadiusPx);
- }
- });
+ setOutlineProvider(mViewBounds);
}
- @Override
- protected void onFinishInflate() {
- mMaxDim = mConfig.taskStackMaxDim;
+ /** Set callback */
+ void setCallbacks(TaskViewCallbacks cb) {
+ mCb = cb;
+ }
- // By default, all views are clipped to other views in their stack
- mClipViewInStack = true;
+ /** Gets the task */
+ Task getTask() {
+ return mTask;
+ }
+
+ /** Returns the view bounds. */
+ AnimateableViewBounds getViewBounds() {
+ return mViewBounds;
+ }
+ @Override
+ protected void onFinishInflate() {
// Bind the views
mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
- mLockToAppButtonView = findViewById(R.id.lock_to_app);
-
- if (mTaskDataLoaded) {
- onTaskDataLoaded();
- }
+ mFooterView = (TaskFooterView) findViewById(R.id.lock_to_app);
+ mFooterView.setCallbacks(this);
}
@Override
@@ -148,96 +130,48 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
- // Measure the bar view, thumbnail, and lock-to-app buttons
+ // Measure the bar view, thumbnail, and footer
mBarView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mConfig.taskBarHeight, MeasureSpec.EXACTLY));
- mLockToAppButtonView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ mFooterView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mConfig.taskViewLockToAppButtonHeight,
MeasureSpec.EXACTLY));
- // Measure the thumbnail height to be the same as the width
- mThumbnailView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY));
+ if (mIsFullScreenView) {
+ // Measure the thumbnail height to be the full dimensions
+ mThumbnailView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ } else {
+ // Measure the thumbnail to be square
+ mThumbnailView.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY));
+ }
setMeasuredDimension(width, height);
}
- /** Set callback */
- void setCallbacks(TaskViewCallbacks cb) {
- mCb = cb;
- }
-
- /** Gets the task */
- Task getTask() {
- return mTask;
- }
-
/** Synchronizes this view's properties with the task's transform */
void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform, int duration) {
// Update the bar view
mBarView.updateViewPropertiesToTaskTransform(toTransform, duration);
- // Check to see if any properties have changed, and update the task view
- if (duration > 0) {
- ViewPropertyAnimator anim = animate();
- boolean useLayers = false;
-
- // Animate to the final state
- if (toTransform.hasTranslationYChangedFrom(getTranslationY())) {
- anim.translationY(toTransform.translationY);
- }
- if (Constants.DebugFlags.App.EnableShadows &&
- toTransform.hasTranslationZChangedFrom(getTranslationZ())) {
- anim.translationZ(toTransform.translationZ);
- }
- if (toTransform.hasScaleChangedFrom(getScaleX())) {
- anim.scaleX(toTransform.scale)
- .scaleY(toTransform.scale)
- .setUpdateListener(mUpdateDimListener);
- useLayers = true;
- }
- if (toTransform.hasAlphaChangedFrom(getAlpha())) {
- // Use layers if we animate alpha
- anim.alpha(toTransform.alpha);
- useLayers = true;
- }
- if (useLayers) {
- anim.withLayer();
- }
- anim.setStartDelay(toTransform.startDelay)
- .setDuration(duration)
- .setInterpolator(mConfig.fastOutSlowInInterpolator)
- .start();
- } else {
- // Set the changed properties
- if (toTransform.hasTranslationYChangedFrom(getTranslationY())) {
- setTranslationY(toTransform.translationY);
- }
+ // 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) {
if (Constants.DebugFlags.App.EnableShadows &&
toTransform.hasTranslationZChangedFrom(getTranslationZ())) {
setTranslationZ(toTransform.translationZ);
}
- if (toTransform.hasScaleChangedFrom(getScaleX())) {
- setScaleX(toTransform.scale);
- setScaleY(toTransform.scale);
- updateDimOverlayFromScale();
- }
- if (toTransform.hasAlphaChangedFrom(getAlpha())) {
- setAlpha(toTransform.alpha);
- }
+ return;
}
+
+ // Apply the transform
+ toTransform.applyToTaskView(this, duration, mConfig.fastOutSlowInInterpolator,
+ mUpdateDimListener);
}
/** Resets this view's properties */
void resetViewProperties() {
- setTranslationX(0f);
- setTranslationY(0f);
- if (Constants.DebugFlags.App.EnableShadows) {
- setTranslationZ(0f);
- }
- setScaleX(1f);
- setScaleY(1f);
- setAlpha(1f);
setDim(0);
- invalidate();
+ TaskViewTransform.reset(this);
}
/**
@@ -262,20 +196,13 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
/** Prepares this task view for the enter-recents animations. This is called earlier in the
* first layout because the actual animation into recents may take a long time. */
- public void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask, int offsetY,
- int offscreenY) {
+ public void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask, int offscreenY) {
if (mConfig.launchedFromAppWithScreenshot) {
if (isTaskViewLaunchTargetTask) {
- // Hide the task view as we are going to animate the full screenshot into view
- // and then replace it with this view once we are done
- setVisibility(View.INVISIBLE);
// Also hide the front most task bar view so we can animate it in
mBarView.prepareEnterRecentsAnimation();
} else {
- // Top align the task views
- setTranslationY(offsetY);
- setScaleX(1f);
- setScaleY(1f);
+ // Don't do anything for the side views
}
} else if (mConfig.launchedFromAppWithThumbnail) {
@@ -300,49 +227,57 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
/** Animates this task view as it enters recents */
public void startEnterRecentsAnimation(final ViewAnimation.TaskViewEnterContext ctx) {
TaskViewTransform transform = ctx.currentTaskTransform;
+ Rect taskRect = ctx.currentTaskRect;
if (mConfig.launchedFromAppWithScreenshot) {
- if (ctx.isCurrentTaskLaunchTarget) {
- // Animate the full screenshot down first, before swapping with this task view
- ctx.fullScreenshotView.animateOnEnterRecents(ctx, new Runnable() {
- @Override
- public void run() {
- // Animate the task bar of the first task view
- mBarView.startEnterRecentsAnimation(0, mEnableThumbnailClip);
- setVisibility(View.VISIBLE);
- // Animate the footer into view
- animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration);
- // Decrement the post animation trigger
- ctx.postAnimationTrigger.decrement();
- }
- });
- } else {
- // Animate the tasks down behind the full screenshot
- animate()
- .scaleX(transform.scale)
- .scaleY(transform.scale)
- .translationY(transform.translationY)
- .setStartDelay(0)
- .setUpdateListener(null)
- .setInterpolator(mConfig.linearOutSlowInInterpolator)
- .setDuration(475)
- .withLayer()
+ if (mTask.isLaunchTarget) {
+ // XXX: We would have to animate the trasnlationY of the task view bar along with the clip and
+ // reset it at the bottom
+
+ // XXX: This should actually be the inset on the current app...
+ mViewBounds.animateClipTop(taskRect.top, mConfig.taskViewEnterFromHomeDuration * 5);
+ mViewBounds.animateClipBottom(getMeasuredHeight() - taskRect.bottom, mConfig.taskViewEnterFromHomeDuration * 5);
+
+ animate().scaleX(((float) taskRect.width() / getMeasuredWidth()) * transform.scale)
+ .scaleY(((float) taskRect.width() / getMeasuredWidth()) * transform.scale)
+ .translationY(taskRect.top + transform.translationY)
+ .setDuration(mConfig.taskViewEnterFromHomeDuration * 5)
.withEndAction(new Runnable() {
@Override
public void run() {
- mEnableThumbnailClip.run();
+ // Animate the task bar of the first task view
+ mBarView.startEnterRecentsAnimation(0, mThumbnailView.enableTaskBarClipAsRunnable(mBarView));
+ // Animate the footer into view (if it is the front most task)
+ animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration);
// Decrement the post animation trigger
ctx.postAnimationTrigger.decrement();
+
+ // XXX Request layout and only start hte next animation after the next
+ // layout
+
+ setIsFullScreen(false);
+ mThumbnailView.unbindFromScreenshot();
+
+ // Recycle the full screen screenshot
+ AlternateRecentsComponent.consumeLastScreenshot();
}
})
+ .withLayer()
.start();
+ } else {
+ // Otherwise, just enable the thumbnail clip
+ mThumbnailView.enableTaskBarClip(mBarView);
+
+ // Animate the footer into view
+ animateFooterVisibility(true, 0);
}
ctx.postAnimationTrigger.increment();
} else if (mConfig.launchedFromAppWithThumbnail) {
- if (ctx.isCurrentTaskLaunchTarget) {
+ if (mTask.isLaunchTarget) {
// Animate the task bar of the first task view
- mBarView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay, mEnableThumbnailClip);
+ mBarView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay,
+ mThumbnailView.enableTaskBarClipAsRunnable(mBarView));
// Animate the dim into view as well
ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", getDimOverlayFromScale());
@@ -360,10 +295,9 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
ctx.postAnimationTrigger.increment();
// Animate the footer into view
- animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration
- );
+ animateFooterVisibility(true, mConfig.taskBarEnterAnimDuration);
} else {
- mEnableThumbnailClip.run();
+ mThumbnailView.enableTaskBarClip(mBarView);
}
} else if (mConfig.launchedFromHome) {
@@ -386,7 +320,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
.withEndAction(new Runnable() {
@Override
public void run() {
- mEnableThumbnailClip.run();
+ mThumbnailView.enableTaskBarClip(mBarView);
// Decrement the post animation trigger
ctx.postAnimationTrigger.decrement();
}
@@ -395,11 +329,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
ctx.postAnimationTrigger.increment();
// Animate the footer into view
- animateFooterVisibility(true, mConfig.taskViewEnterFromHomeDuration
- );
+ animateFooterVisibility(true, mConfig.taskViewEnterFromHomeDuration);
+
} else {
// Otherwise, just enable the thumbnail clip
- mEnableThumbnailClip.run();
+ mThumbnailView.enableTaskBarClip(mBarView);
// Animate the footer into view
animateFooterVisibility(true, 0);
@@ -424,7 +358,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
public void startLaunchTaskAnimation(final Runnable r, boolean isLaunchingTask) {
if (isLaunchingTask) {
// Disable the thumbnail clip and animate the bar out
- mBarView.startLaunchTaskAnimation(mDisableThumbnailClip, r);
+ mBarView.startLaunchTaskAnimation(mThumbnailView.disableTaskBarClipAsRunnable(), r);
// Animate the dim
if (mDim > 0) {
@@ -478,32 +412,23 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
mBarView.setNoUserInteractionState();
}
- /** Enable the hw layers on this task view */
- void enableHwLayers() {
- mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
- mBarView.enableHwLayers();
- mLockToAppButtonView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
+ /** Sets whether this task view is full screen or not. */
+ void setIsFullScreen(boolean isFullscreen) {
+ mIsFullScreenView = isFullscreen;
+ mBarView.setIsFullscreen(isFullscreen);
+ if (isFullscreen) {
+ // If we are full screen, then disable the bottom outline clip for the footer
+ mViewBounds.setOutlineClipBottom(0);
+ }
}
- /** Disable the hw layers on this task view */
- void disableHwLayers() {
- mThumbnailView.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
- mBarView.disableHwLayers();
- mLockToAppButtonView.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
+ /** Returns whether this task view should currently be drawn as a full screen view. */
+ boolean isFullScreenView() {
+ return mIsFullScreenView;
}
/** Sets the stubbed state of this task view. */
void setStubState(boolean isStub) {
- if (!mIsStub && isStub) {
- // This is now a stub task view, so clip to the bar height, hide the thumbnail
- setClipBounds(new Rect(0, 0, getMeasuredWidth(), mBarView.getMeasuredHeight()));
- mThumbnailView.setVisibility(View.INVISIBLE);
- // Temporary
- mBarView.mActivityDescription.setText("Stub");
- } else if (mIsStub && !isStub) {
- setClipBounds(null);
- mThumbnailView.setVisibility(View.VISIBLE);
- }
mIsStub = isStub;
}
@@ -512,7 +437,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
* view.
*/
boolean shouldClipViewInStack() {
- return mClipViewInStack && (getVisibility() == View.VISIBLE);
+ return mClipViewInStack && !mIsFullScreenView && (getVisibility() == View.VISIBLE);
}
/** Sets whether this view should be clipped, or clipped against. */
@@ -523,75 +448,19 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
}
}
- void setClipFromBottom(int clipFromBottom) {
- clipFromBottom = Math.max(0, Math.min(getMeasuredHeight(), clipFromBottom));
- if (mClipFromBottom != clipFromBottom) {
- mClipFromBottom = clipFromBottom;
- invalidateOutline();
- }
- }
-
- /** Sets the footer height. */
- public void setFooterHeight(int footerHeight) {
- if (footerHeight != mFooterHeight) {
- mFooterHeight = footerHeight;
- invalidateOutline();
- invalidate(0, getMeasuredHeight() - mMaxFooterHeight, getMeasuredWidth(),
- getMeasuredHeight());
- }
- }
-
- /** Gets the footer height. */
- public int getFooterHeight() {
- return mFooterHeight;
- }
-
/** Gets the max footer height. */
public int getMaxFooterHeight() {
- return mMaxFooterHeight;
+ return mFooterView.mMaxFooterHeight;
}
/** Animates the footer into and out of view. */
- public void animateFooterVisibility(boolean visible, int duration) {
- if (!mTask.lockToThisTask) {
- if (mLockToAppButtonView.getVisibility() == View.VISIBLE) {
- mLockToAppButtonView.setVisibility(View.INVISIBLE);
- }
- return;
- }
- if (mMaxFooterHeight <= 0) return;
-
- if (mFooterAnimator != null) {
- mFooterAnimator.removeAllListeners();
- mFooterAnimator.cancel();
- }
- int height = visible ? mMaxFooterHeight : 0;
- if (visible && mLockToAppButtonView.getVisibility() != View.VISIBLE) {
- if (duration > 0) {
- setFooterHeight(0);
- } else {
- setFooterHeight(mMaxFooterHeight);
- }
- mLockToAppButtonView.setVisibility(View.VISIBLE);
- }
- if (duration > 0) {
- mFooterAnimator = ObjectAnimator.ofInt(this, "footerHeight", height);
- mFooterAnimator.setDuration(duration);
- mFooterAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
- if (!visible) {
- mFooterAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mLockToAppButtonView.setVisibility(View.INVISIBLE);
- }
- });
- }
- mFooterAnimator.start();
- } else {
- if (!visible) {
- mLockToAppButtonView.setVisibility(View.INVISIBLE);
- }
- }
+ void animateFooterVisibility(boolean visible, int duration) {
+ // Hide the footer if we are a full screen view
+ if (mIsFullScreenView) return;
+ // Hide the footer if the current task can not be locked to
+ if (!mTask.lockToTaskEnabled || !mTask.lockToThisTask) return;
+ // Otherwise, animate the visibility
+ mFooterView.animateFooterVisibility(visible, duration);
}
/** Returns the current dim. */
@@ -619,6 +488,8 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
setDim(getDimOverlayFromScale());
}
+ /**** View drawing ****/
+
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
@@ -631,13 +502,29 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
@Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
- if (mIsStub && (child == mThumbnailView)) {
+ if (mIsStub && (child != mBarView)) {
// Skip the thumbnail view if we are in stub mode
return false;
}
return super.drawChild(canvas, child, drawingTime);
}
+ /** Enable the hw layers on this task view */
+ void enableHwLayers() {
+ mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
+ mBarView.enableHwLayers();
+ mFooterView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
+ }
+
+ /** Disable the hw layers on this task view */
+ void disableHwLayers() {
+ mThumbnailView.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
+ mBarView.disableHwLayers();
+ mFooterView.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
+ }
+
+ /**** View focus state ****/
+
/**
* Sets the focused task explicitly. We need a separate flag because requestFocus() won't happen
* if the view is not currently visible, or we are in touch state (where we still want to keep
@@ -691,14 +578,18 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
public void onTaskDataLoaded() {
if (mThumbnailView != null && mBarView != null) {
// Bind each of the views to the new task data
- mThumbnailView.rebindToTask(mTask);
+ if (mIsFullScreenView) {
+ mThumbnailView.bindToScreenshot(AlternateRecentsComponent.getLastScreenshot());
+ } else {
+ mThumbnailView.rebindToTask(mTask);
+ }
mBarView.rebindToTask(mTask);
// Rebind any listeners
if (Constants.DebugFlags.App.EnableTaskFiltering) {
mBarView.mApplicationIcon.setOnClickListener(this);
}
mBarView.mDismissButton.setOnClickListener(this);
- mLockToAppButtonView.setOnClickListener(this);
+ mFooterView.setOnClickListener(this);
if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
if (mConfig.developerOptionsEnabled) {
mBarView.mApplicationIcon.setOnLongClickListener(this);
@@ -720,7 +611,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
mBarView.mApplicationIcon.setOnClickListener(null);
}
mBarView.mDismissButton.setOnClickListener(null);
- mLockToAppButtonView.setOnClickListener(null);
+ mFooterView.setOnClickListener(null);
if (Constants.DebugFlags.App.EnableDevAppInfoOnLongPress) {
mBarView.mApplicationIcon.setOnLongClickListener(null);
}
@@ -733,6 +624,21 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
setOnClickListener(enabled ? this : null);
}
+ /**** TaskFooterView.TaskFooterViewCallbacks ****/
+
+ @Override
+ public void onTaskFooterHeightChanged(int height, int maxHeight) {
+ if (mIsFullScreenView) {
+ // Disable the bottom outline clip when fullscreen
+ mViewBounds.setOutlineClipBottom(0);
+ } else {
+ // Update the bottom clip in our outline provider
+ mViewBounds.setOutlineClipBottom(maxHeight - height);
+ }
+ }
+
+ /**** View.OnClickListener Implementation ****/
+
@Override
public void onClick(final View v) {
// We purposely post the handler delayed to allow for the touch feedback to draw
@@ -752,13 +658,15 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
});
// Hide the footer
tv.animateFooterVisibility(false, mConfig.taskViewRemoveAnimDuration);
- } else if (v == tv || v == mLockToAppButtonView) {
- mCb.onTaskViewClicked(tv, tv.getTask(), (v == mLockToAppButtonView));
+ } else if (v == tv || v == mFooterView) {
+ mCb.onTaskViewClicked(tv, tv.getTask(), (v == mFooterView));
}
}
}, 125);
}
+ /**** View.OnLongClickListener Implementation ****/
+
@Override
public boolean onLongClick(View v) {
if (v == mBarView.mApplicationIcon) {
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 b351b03..d583c20 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -16,7 +16,12 @@
package com.android.systemui.recents.views;
+import android.animation.ValueAnimator;
import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+import android.view.animation.Interpolator;
+import com.android.systemui.recents.Constants;
/* The transform state for a task view */
@@ -77,6 +82,73 @@ public class TaskViewTransform {
return (Float.compare(translationZ, v) != 0);
}
+ /** Applies this transform to a view. */
+ public void applyToTaskView(View v, int duration, Interpolator interp,
+ ValueAnimator.AnimatorUpdateListener scaleUpdateListener) {
+ // Check to see if any properties have changed, and update the task view
+ if (duration > 0) {
+ ViewPropertyAnimator anim = v.animate();
+ boolean useLayers = false;
+
+ // Animate to the final state
+ if (hasTranslationYChangedFrom(v.getTranslationY())) {
+ anim.translationY(translationY);
+ }
+ if (Constants.DebugFlags.App.EnableShadows &&
+ hasTranslationZChangedFrom(v.getTranslationZ())) {
+ anim.translationZ(translationZ);
+ }
+ if (hasScaleChangedFrom(v.getScaleX())) {
+ anim.scaleX(scale)
+ .scaleY(scale)
+ .setUpdateListener(scaleUpdateListener);
+ useLayers = true;
+ }
+ if (hasAlphaChangedFrom(v.getAlpha())) {
+ // Use layers if we animate alpha
+ anim.alpha(alpha);
+ useLayers = true;
+ }
+ if (useLayers) {
+ anim.withLayer();
+ }
+ anim.setStartDelay(startDelay)
+ .setDuration(duration)
+ .setInterpolator(interp)
+ .start();
+ } else {
+ // Set the changed properties
+ if (hasTranslationYChangedFrom(v.getTranslationY())) {
+ v.setTranslationY(translationY);
+ }
+ if (Constants.DebugFlags.App.EnableShadows &&
+ hasTranslationZChangedFrom(v.getTranslationZ())) {
+ v.setTranslationZ(translationZ);
+ }
+ if (hasScaleChangedFrom(v.getScaleX())) {
+ v.setScaleX(scale);
+ v.setScaleY(scale);
+ scaleUpdateListener.onAnimationUpdate(null);
+ }
+ if (hasAlphaChangedFrom(v.getAlpha())) {
+ v.setAlpha(alpha);
+ }
+ }
+ }
+
+ /** Reset the transform on a view. */
+ public static void reset(View v) {
+ v.setTranslationX(0f);
+ v.setTranslationY(0f);
+ if (Constants.DebugFlags.App.EnableShadows) {
+ v.setTranslationZ(0f);
+ }
+ v.setScaleX(1f);
+ v.setScaleY(1f);
+ v.setAlpha(1f);
+ v.invalidate();
+ }
+
@Override
public String toString() {
return "TaskViewTransform delay: " + startDelay + " y: " + translationY + " z: " + translationZ +
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 e50a5cf..3705cb5 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.graphics.Rect;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
/* Common code related to view animations */
@@ -23,27 +24,22 @@ public class ViewAnimation {
/* The animation context for a task view animation into Recents */
public static class TaskViewEnterContext {
- // The full screenshot view that we are animating down
- FullscreenTransitionOverlayView fullScreenshotView;
- // The transform of the target task view that we are animating into
- TaskViewTransform targetTaskTransform;
// 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;
// These following properties are updated for each task view we start the enter animation on
+ // The task rect for the current stack
+ Rect currentTaskRect;
// The transform of the current task view
TaskViewTransform currentTaskTransform;
- // Whether this is the front most task view
- boolean isCurrentTaskLaunchTarget;
// The view index of the current task view
int currentStackViewIndex;
// The total number of task views
int currentStackViewCount;
- public TaskViewEnterContext(FullscreenTransitionOverlayView fss, ReferenceCountedTrigger t) {
- fullScreenshotView = fss;
+ public TaskViewEnterContext(ReferenceCountedTrigger t) {
postAnimationTrigger = t;
}
}
@@ -53,6 +49,7 @@ 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;
+
// The translationY to apply to a TaskView to move it off the bottom of the task stack
int offscreenTranslationY;