diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 0b5383acf4d21..d232e00d02e2d 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -297,7 +297,7 @@
android:screenOrientation="behind"
android:resizeableActivity="true"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
- android:theme="@style/RecentsTheme.Wallpaper">
+ android:theme="@style/RecentsTheme.Grid">
diff --git a/packages/SystemUI/res/layout-sw600dp/recents_grid.xml b/packages/SystemUI/res/layout-sw600dp/recents_grid.xml
index cff770ae049ab..1a054a5347258 100644
--- a/packages/SystemUI/res/layout-sw600dp/recents_grid.xml
+++ b/packages/SystemUI/res/layout-sw600dp/recents_grid.xml
@@ -13,22 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_stack_action_button.xml b/packages/SystemUI/res/layout/recents_stack_action_button.xml
index 541000b78f8b6..34b4e1771af54 100644
--- a/packages/SystemUI/res/layout/recents_stack_action_button.xml
+++ b/packages/SystemUI/res/layout/recents_stack_action_button.xml
@@ -33,4 +33,5 @@
android:fontFamily="sans-serif-medium"
android:background="@drawable/recents_stack_action_background"
android:visibility="invisible"
- android:forceHasOverlappingRendering="false" />
+ android:forceHasOverlappingRendering="false"
+ style="?attr/clearAllStyle" />
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index ad65f82ab956f..a2298663740e2 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -30,6 +30,8 @@
+
+
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 12f7881c11d9b..2f7174a6a89e3 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -697,4 +697,19 @@
48dp
+
+
+
+ 15dp
+ 70dp
+ 15dp
+ 90dp
+
+ 0dp
+ 30dp
+ 15dp
+ 0dp
+
+ 15dp
+
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 6661f076d8481..78fc9f979999b 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -34,6 +34,30 @@
- @null
- true
- true
+ - @style/ClearAllButtonDefaultMargins
+
+
+
+
+
+
+
+
diff --git a/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java b/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java
index e1e654d58be75..71c21489554b0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/grid/RecentsGridActivity.java
@@ -20,16 +20,22 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import android.app.Activity;
import android.content.Intent;
import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
+import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
import android.view.WindowManager;
+import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.ScaleAnimation;
+import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
-import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
@@ -61,17 +67,23 @@ import com.android.systemui.recents.model.TaskStack;
import com.android.systemui.recents.views.TaskView;
import java.util.ArrayList;
-import java.util.List;
+import java.util.Arrays;
/**
* The main grid recents activity started by the RecentsImpl.
*/
-public class RecentsGridActivity extends Activity implements ViewTreeObserver.OnPreDrawListener {
+public class RecentsGridActivity extends Activity {
+ public final static int MAX_VISIBLE_TASKS = 9;
+
private final static String TAG = "RecentsGridActivity";
+ private final static int TITLE_BAR_HEIGHT_DP = 64;
+
+ private ArrayList mMargins = new ArrayList<>();
private TaskStack mTaskStack;
- private List mTasks = new ArrayList<>();
- private List mTaskViews = new ArrayList<>();
+ private ArrayList mTasks = new ArrayList<>();
+ private ArrayList mTaskViews = new ArrayList<>();
+ private ArrayList mTaskViewRects;
private FrameLayout mRecentsView;
private TextView mEmptyView;
private View mClearAllButton;
@@ -80,6 +92,10 @@ public class RecentsGridActivity extends Activity implements ViewTreeObserver.On
private Rect mDisplayRect = new Rect();
private LayoutInflater mInflater;
private boolean mTouchExplorationEnabled;
+ private Point mScreenSize;
+ private int mTitleBarHeightPx;
+ private int mStatusBarHeightPx;
+ private int mNavigationBarHeightPx;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -87,12 +103,28 @@ public class RecentsGridActivity extends Activity implements ViewTreeObserver.On
setContentView(R.layout.recents_grid);
SystemServicesProxy ssp = Recents.getSystemServices();
+ Resources res = getResources();
+ Integer[] margins = {
+ res.getDimensionPixelSize(R.dimen.recents_grid_margin_left),
+ res.getDimensionPixelSize(R.dimen.recents_grid_margin_top),
+ res.getDimensionPixelSize(R.dimen.recents_grid_margin_right),
+ res.getDimensionPixelSize(R.dimen.recents_grid_margin_bottom),
+ };
+ mMargins.addAll(Arrays.asList(margins));
+
mInflater = LayoutInflater.from(this);
Configuration appConfiguration = Utilities.getAppConfiguration(this);
mDisplayRect = ssp.getDisplayRect();
mLastDisplayOrientation = appConfiguration.orientation;
mLastDisplayDensity = appConfiguration.densityDpi;
mTouchExplorationEnabled = ssp.isTouchExplorationEnabled();
+ mScreenSize = new Point();
+ getWindowManager().getDefaultDisplay().getRealSize(mScreenSize);
+ DisplayMetrics metrics = res.getDisplayMetrics();
+ mTitleBarHeightPx = (int) (TITLE_BAR_HEIGHT_DP *
+ ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT));
+ mStatusBarHeightPx = res.getDimensionPixelSize(R.dimen.status_bar_height);
+ mNavigationBarHeightPx = res.getDimensionPixelSize(R.dimen.navigation_bar_height);
mRecentsView = (FrameLayout) findViewById(R.id.recents_view);
mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
@@ -100,8 +132,7 @@ public class RecentsGridActivity extends Activity implements ViewTreeObserver.On
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
getWindow().getAttributes().privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
- LinearLayout recentsContainer = (LinearLayout) findViewById(R.id.recents_container);
- mEmptyView = (TextView) mInflater.inflate(R.layout.recents_empty, recentsContainer, false);
+ mEmptyView = (TextView) mInflater.inflate(R.layout.recents_empty, mRecentsView, false);
mClearAllButton = findViewById(R.id.button);
FrameLayout.LayoutParams emptyViewLayoutParams = new FrameLayout.LayoutParams(
@@ -111,8 +142,8 @@ public class RecentsGridActivity extends Activity implements ViewTreeObserver.On
mRecentsView.addView(mEmptyView);
mClearAllButton.setVisibility(View.VISIBLE);
- LinearLayout.LayoutParams lp =
- (LinearLayout.LayoutParams) mClearAllButton.getLayoutParams();
+ FrameLayout.LayoutParams lp =
+ (FrameLayout.LayoutParams) mClearAllButton.getLayoutParams();
lp.gravity = Gravity.END;
mClearAllButton.setOnClickListener(v -> {
@@ -154,6 +185,57 @@ public class RecentsGridActivity extends Activity implements ViewTreeObserver.On
return null;
}
+ /**
+ * Starts animations for each task view to either enlarge it to the size of the screen (when
+ * launching a task), or (if {@code reverse} is true, to reduce it from the size of the screen
+ * back to its place in the recents layout (when opening recents).
+ * @param animationListener An animation listener for executing code before or after the
+ * animations run.
+ * @param reverse Whether the blow-up animations should be run in reverse.
+ */
+ private void startBlowUpAnimations(Animation.AnimationListener animationListener,
+ boolean reverse) {
+ if (mTaskViews.size() == 0) {
+ return;
+ }
+ int screenWidth = mLastDisplayOrientation == Configuration.ORIENTATION_LANDSCAPE
+ ? mScreenSize.x : mScreenSize.y;
+ int screenHeight = mLastDisplayOrientation == Configuration.ORIENTATION_LANDSCAPE
+ ? mScreenSize.y : mScreenSize.x;
+ screenHeight -= mStatusBarHeightPx + mNavigationBarHeightPx;
+ for (int i = 0; i < mTaskViews.size(); i++) {
+ View tv = mTaskViews.get(i);
+ AnimationSet animations = new AnimationSet(true /* shareInterpolator */);
+ animations.setInterpolator(new DecelerateInterpolator());
+ if (i == 0 && animationListener != null) {
+ animations.setAnimationListener(animationListener);
+ }
+ animations.setFillBefore(reverse);
+ animations.setFillAfter(!reverse);
+ Rect initialRect = mTaskViewRects.get(mTaskViewRects.size() - 1 - i);
+ int xDelta = - initialRect.left;
+ int yDelta = - initialRect.top - mTitleBarHeightPx + mStatusBarHeightPx;
+ TranslateAnimation translate = new TranslateAnimation(
+ reverse ? xDelta : 0, reverse ? 0 : xDelta,
+ reverse ? yDelta : 0, reverse ? 0 : yDelta);
+ translate.setDuration(250);
+ animations.addAnimation(translate);
+
+
+ float xScale = (float) screenWidth / (float) initialRect.width();
+ float yScale = (float) screenHeight /
+ ((float) initialRect.height() - mTitleBarHeightPx);
+ ScaleAnimation scale = new ScaleAnimation(
+ reverse ? xScale : 1, reverse ? 1 : xScale,
+ reverse ? yScale : 1, reverse ? 1 : yScale,
+ Animation.ABSOLUTE, 0, Animation.ABSOLUTE, mStatusBarHeightPx);
+ scale.setDuration(300);
+ animations.addAnimation(scale);
+
+ tv.startAnimation(animations);
+ }
+ }
+
private void updateControlVisibility() {
boolean empty = (mTasks.size() == 0);
mClearAllButton.setVisibility(empty ? View.INVISIBLE : View.VISIBLE);
@@ -163,7 +245,7 @@ public class RecentsGridActivity extends Activity implements ViewTreeObserver.On
}
}
- private void updateRecentsTasks() {
+ private void updateModel() {
RecentsTaskLoader loader = Recents.getTaskLoader();
RecentsTaskLoadPlan plan = RecentsImpl.consumeInstanceLoadPlan();
if (plan == null) {
@@ -174,29 +256,66 @@ public class RecentsGridActivity extends Activity implements ViewTreeObserver.On
if (!plan.hasTasks()) {
loader.preloadTasks(plan, -1, !launchState.launchedFromHome);
}
- int numVisibleTasks = 9;
mTaskStack = plan.getTaskStack();
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
loadOpts.runningTaskId = launchState.launchedToTaskId;
- loadOpts.numVisibleTasks = numVisibleTasks;
- loadOpts.numVisibleTaskThumbnails = numVisibleTasks;
+ loadOpts.numVisibleTasks = MAX_VISIBLE_TASKS;
+ loadOpts.numVisibleTaskThumbnails = MAX_VISIBLE_TASKS;
loader.loadTasks(this, plan, loadOpts);
mTasks = mTaskStack.getStackTasks();
+ }
- updateControlVisibility();
-
- clearTaskViews();
+ private void updateViews() {
+ int screenWidth = mLastDisplayOrientation == Configuration.ORIENTATION_LANDSCAPE
+ ? mScreenSize.x : mScreenSize.y;
+ int screenHeight = mLastDisplayOrientation == Configuration.ORIENTATION_LANDSCAPE
+ ? mScreenSize.y : mScreenSize.x;
+ int paddingPixels = getResources().getDimensionPixelSize(
+ R.dimen.recents_grid_inter_task_padding);
+ mTaskViewRects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
+ mTasks.size(), screenWidth, screenHeight, getAppRectRatio(), paddingPixels,
+ mMargins, mTitleBarHeightPx);
+ boolean recycleViews = (mTaskViews.size() == mTasks.size());
+ if (!recycleViews) {
+ clearTaskViews();
+ }
for (int i = 0; i < mTasks.size(); i++) {
Task task = mTasks.get(i);
- TaskView taskView = createView();
+ // We keep the same ordering in the model as other Recents flavors (older tasks are
+ // first in the stack) so that the logic can be similar, but we reverse the order
+ // when placing views on the screen so that most recent tasks are displayed first.
+ Rect rect = mTaskViewRects.get(mTaskViewRects.size() - 1 - i);
+ TaskView taskView;
+ if (recycleViews) {
+ taskView = mTaskViews.get(i);
+ } else {
+ taskView = createView();
+ }
taskView.onTaskBound(task, mTouchExplorationEnabled, mLastDisplayOrientation,
mDisplayRect);
Recents.getTaskLoader().loadTaskData(task);
taskView.setTouchEnabled(true);
// Show dismiss button right away.
taskView.startNoUserInteractionAnimation();
- mTaskViews.add(taskView);
+ taskView.setLayoutParams(new FrameLayout.LayoutParams(rect.width(), rect.height()));
+ taskView.setTranslationX(rect.left);
+ taskView.setTranslationY(rect.top);
+ if (!recycleViews) {
+ mRecentsView.addView(taskView);
+ mTaskViews.add(taskView);
+ }
+ }
+ updateControlVisibility();
+ }
+
+ private float getAppRectRatio() {
+ if (mLastDisplayOrientation == Configuration.ORIENTATION_LANDSCAPE) {
+ return (float) mScreenSize.x /
+ (float) (mScreenSize.y - mStatusBarHeightPx - mNavigationBarHeightPx);
+ } else {
+ return (float) mScreenSize.y /
+ (float) (mScreenSize.x - mStatusBarHeightPx - mNavigationBarHeightPx);
}
}
@@ -204,13 +323,23 @@ public class RecentsGridActivity extends Activity implements ViewTreeObserver.On
protected void onStart() {
super.onStart();
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
- mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
- }
+ updateModel();
+ updateViews();
+ if (mTaskViews.size() > 0) {
+ mTaskViews.get(mTaskViews.size() - 1).bringToFront();
+ }
+ startBlowUpAnimations(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationStart(Animation animation) { }
- @Override
- public void onResume() {
- super.onResume();
- updateRecentsTasks();
+ @Override
+ public void onAnimationEnd(Animation animation) {
+ updateViews();
+ }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) { }
+ }, true /* reverse */);
}
@Override
@@ -237,37 +366,13 @@ public class RecentsGridActivity extends Activity implements ViewTreeObserver.On
// Notify of the config change.
Configuration newDeviceConfiguration = Utilities.getAppConfiguration(this);
mDisplayRect = Recents.getSystemServices().getDisplayRect();
- mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
- mRecentsView.requestLayout();
int numStackTasks = mTaskStack.getStackTaskCount();
EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */,
mLastDisplayOrientation != newDeviceConfiguration.orientation,
mLastDisplayDensity != newDeviceConfiguration.densityDpi, numStackTasks > 0));
mLastDisplayOrientation = newDeviceConfiguration.orientation;
mLastDisplayDensity = newDeviceConfiguration.densityDpi;
- }
-
- @Override
- public boolean onPreDraw() {
- mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
- int width = mRecentsView.getWidth();
- int height = mRecentsView.getHeight();
-
- List rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
- mTasks.size(), width, height, false /* allowLineOfThree */, 30 /* padding */);
- removeTaskViews();
- for (int i = 0; i < rects.size(); i++) {
- Rect rect = rects.get(i);
- // We keep the same ordering in the model as other Recents flavors (older tasks are
- // first in the stack) so that the logic can be similar, but we reverse the order
- // when placing views on the screen so that most recent tasks are displayed first.
- View taskView = mTaskViews.get(rects.size() - 1 - i);
- taskView.setLayoutParams(new FrameLayout.LayoutParams(rect.width(), rect.height()));
- taskView.setTranslationX(rect.left);
- taskView.setTranslationY(rect.top);
- mRecentsView.addView(taskView);
- }
- return true;
+ updateViews();
}
void dismissRecentsToHome() {
@@ -360,7 +465,8 @@ public class RecentsGridActivity extends Activity implements ViewTreeObserver.On
EventBus.getDefault().send(new DeleteTaskDataEvent(tasks.get(i)));
}
mTasks = new ArrayList<>();
- updateRecentsTasks();
+ updateModel();
+ updateViews();
MetricsLogger.action(this, MetricsEvent.OVERVIEW_DISMISS_ALL);
}
@@ -390,6 +496,9 @@ public class RecentsGridActivity extends Activity implements ViewTreeObserver.On
}
public final void onBusEvent(LaunchTaskEvent event) {
+ event.taskView.bringToFront();
startActivity(event.task.key.baseIntent);
+ // Eventually we should start blow-up animations here, but we need to make sure it's done
+ // in parallel with starting the activity so that we don't introduce unneeded latency.
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithm.java
index 057aa5497bf4b..648f2f023fdff 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithm.java
@@ -19,66 +19,111 @@ import android.graphics.Rect;
import android.util.Log;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
class TaskGridLayoutAlgorithm {
- private static final String TAG = "TaskGridLayoutAlgorithm";
-
- static List getRectsForTaskCount(int count, int containerWidth, int containerHeight,
- boolean allowLineOfThree, int padding) {
- return getRectsForTaskCount(count, containerWidth, containerHeight, allowLineOfThree,
- padding, null);
+ public enum VerticalGravity {
+ START, END, CENTER
}
- static List getRectsForTaskCount(int count, int containerWidth, int containerHeight,
- boolean allowLineOfThree, int padding, Rect preCalculatedTile) {
- int singleLineMaxCount = allowLineOfThree ? 3 : 2;
- List rects = new ArrayList<>(count);
+ public static final List ZERO_MARGIN = new ArrayList<>();
+ static {
+ Integer[] zero = {0, 0, 0, 0};
+ ZERO_MARGIN.addAll(Arrays.asList(zero));
+ }
+ private static final String TAG = "TaskGridLayoutAlgorithm";
+
+ /**
+ * Calculates the adequate rectangles for the specified number of tasks to be layed out on
+ * the screen.
+ * @param count The number of task views to layout.
+ * @param containerWidth The width of the whole area containing those tasks.
+ * @param containerHeight The height of the whole area containing those tasks.
+ * @param screenRatio The ratio of the device's screen, so that tasks have the same aspect
+ * ratio (ignoring the title bar).
+ * @param padding The amount of padding, in pixels, in between task views.
+ * @param margins The amount of space to be left blank around the area on the left, top, right
+ * and bottom.
+ * @param titleBarHeight The height, in pixels, of the task views title bar.
+ * @return A list of rectangles to be used for layout.
+ */
+ static ArrayList getRectsForTaskCount(int count, int containerWidth, int containerHeight,
+ float screenRatio, int padding, List margins, int titleBarHeight) {
+ return getRectsForTaskCount(count, containerWidth, containerHeight, screenRatio, padding,
+ margins, titleBarHeight, null, VerticalGravity.CENTER);
+ }
+
+ private static ArrayList getRectsForTaskCount(int count, int containerWidth,
+ int containerHeight, float screenRatio, int padding, List margins,
+ int titleBarHeight, Rect preCalculatedTile, VerticalGravity gravity) {
+ ArrayList rects = new ArrayList<>(count);
boolean landscape = (containerWidth > containerHeight);
+ containerWidth -= margins.get(0) + margins.get(2);
+ containerHeight -= margins.get(1) + margins.get(3);
// We support at most 9 tasks in this layout.
- count = Math.min(count, 9);
+ count = Math.min(count, RecentsGridActivity.MAX_VISIBLE_TASKS);
if (count == 0) {
return rects;
}
- if (count <= singleLineMaxCount) {
- if (landscape) {
- // Single line.
- int taskWidth = 0;
- int emptySpace = 0;
- if (preCalculatedTile != null) {
- taskWidth = preCalculatedTile.width();
- emptySpace = containerWidth - (count * taskWidth) - (count - 1) * padding;
- } else {
- // Divide available space in equal parts.
- taskWidth = (containerWidth - (count - 1) * padding) / count;
- }
- for (int i = 0; i < count; i++) {
- int left = emptySpace / 2 + i * taskWidth + i * padding;
- rects.add(new Rect(left, 0, left + taskWidth, containerHeight));
- }
+ if (count <= 3) {
+ // Base case: single line.
+ int taskWidth, taskHeight;
+ if (preCalculatedTile != null) {
+ taskWidth = preCalculatedTile.width();
+ taskHeight = preCalculatedTile.height();
} else {
- // Single column. Divide available space in equal parts.
- int taskHeight = (containerHeight - (count - 1) * padding) / count;
- for (int i = 0; i < count; i++) {
- int top = i * taskHeight + i * padding;
- rects.add(new Rect(0, top, containerWidth, top + taskHeight));
+ // Divide available width in equal parts.
+ int maxTaskWidth = (containerWidth - (count - 1) * padding) / count;
+ int maxTaskHeight = containerHeight;
+ if (maxTaskHeight >= maxTaskWidth / screenRatio + titleBarHeight) {
+ // Width bound.
+ taskWidth = maxTaskWidth;
+ taskHeight = (int) (maxTaskWidth / screenRatio + titleBarHeight);
+ } else {
+ // Height bound.
+ taskHeight = maxTaskHeight;
+ taskWidth = (int) ((taskHeight - titleBarHeight) * screenRatio);
}
}
+ int emptySpaceX = containerWidth - (count * taskWidth) - (count - 1) * padding;
+ int emptySpaceY = containerHeight - taskHeight;
+ for (int i = 0; i < count; i++) {
+ int left = emptySpaceX / 2 + i * taskWidth + i * padding;
+ int top;
+ switch (gravity) {
+ case CENTER:
+ top = emptySpaceY / 2;
+ break;
+ case END:
+ top = emptySpaceY;
+ break;
+ case START:
+ default:
+ top = 0;
+ break;
+ }
+ Rect rect = new Rect(left, top, left + taskWidth, top + taskHeight);
+ rect.offset(margins.get(0), margins.get(1));
+ rects.add(rect);
+ }
} else if (count < 7) {
// Two lines.
int lineHeight = (containerHeight - padding) / 2;
int lineTaskCount = (int) Math.ceil((double) count / 2);
- List rectsA = getRectsForTaskCount(
- lineTaskCount, containerWidth, lineHeight, true /* allowLineOfThree */, padding,
- null);
- List rectsB = getRectsForTaskCount(
- count - lineTaskCount, containerWidth, lineHeight, true /* allowLineOfThree */,
- padding, rectsA.get(0));
- for (Rect rect : rectsB) {
- rect.offset(0, lineHeight + padding);
+ List rectsA = getRectsForTaskCount(lineTaskCount, containerWidth, lineHeight,
+ screenRatio, padding, ZERO_MARGIN, titleBarHeight, null, VerticalGravity.END);
+ List rectsB = getRectsForTaskCount(count - lineTaskCount, containerWidth,
+ lineHeight, screenRatio, padding, ZERO_MARGIN, titleBarHeight, rectsA.get(0),
+ VerticalGravity.START);
+ for (int i = 0; i < rectsA.size(); i++) {
+ rectsA.get(i).offset(margins.get(0), margins.get(1));
+ }
+ for (int i = 0; i < rectsB.size(); i++) {
+ rectsB.get(i).offset(margins.get(0), margins.get(1) + lineHeight + padding);
}
rects.addAll(rectsA);
rects.addAll(rectsB);
@@ -86,19 +131,22 @@ class TaskGridLayoutAlgorithm {
// Three lines.
int lineHeight = (containerHeight - 2 * padding) / 3;
int lineTaskCount = (int) Math.ceil((double) count / 3);
- List rectsA = getRectsForTaskCount(
- lineTaskCount, containerWidth, lineHeight, true /* allowLineOfThree */, padding, null);
- List rectsB = getRectsForTaskCount(
- lineTaskCount, containerWidth, lineHeight, true /* allowLineOfThree */, padding,
- rectsA.get(0));
- List rectsC = getRectsForTaskCount(
- count - (2 * lineTaskCount), containerWidth, lineHeight,
- true /* allowLineOfThree */, padding, rectsA.get(0));
- for (Rect rect : rectsB) {
- rect.offset(0, lineHeight + padding);
+ List rectsA = getRectsForTaskCount(lineTaskCount, containerWidth, lineHeight,
+ screenRatio, padding, ZERO_MARGIN, titleBarHeight, null, VerticalGravity.END);
+ List rectsB = getRectsForTaskCount(lineTaskCount, containerWidth, lineHeight,
+ screenRatio, padding, ZERO_MARGIN, titleBarHeight, rectsA.get(0),
+ VerticalGravity.END);
+ List rectsC = getRectsForTaskCount(count - (2 * lineTaskCount), containerWidth,
+ lineHeight, screenRatio, padding, ZERO_MARGIN, titleBarHeight, rectsA.get(0),
+ VerticalGravity.START);
+ for (int i = 0; i < rectsA.size(); i++) {
+ rectsA.get(i).offset(margins.get(0), margins.get(1));
}
- for (Rect rect : rectsC) {
- rect.offset(0, 2 * (lineHeight + padding));
+ for (int i = 0; i < rectsB.size(); i++) {
+ rectsB.get(i).offset(margins.get(0), margins.get(1) + lineHeight + padding);
+ }
+ for (int i = 0; i < rectsC.size(); i++) {
+ rectsC.get(i).offset(margins.get(0), margins.get(1) + 2 * (lineHeight + padding));
}
rects.addAll(rectsA);
rects.addAll(rectsB);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithmTest.java
index 74b6127448701..a9f811b2cee6b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/recents/grid/TaskGridLayoutAlgorithmTest.java
@@ -19,39 +19,44 @@ import android.graphics.Rect;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.systemui.SysuiTestCase;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
+import org.junit.Test;
+
@SmallTest
public class TaskGridLayoutAlgorithmTest extends SysuiTestCase {
- public void testMethodName_ExpectedBehavior() {
- assertTrue(true);
- }
+ private static final List ZERO_MARGIN = TaskGridLayoutAlgorithm.ZERO_MARGIN;
+ @Test
public void testOneTile() {
List rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
- 1, 1000, 500, false /* allowLineOfThree */, 0 /* padding */);
+ 1, 1000, 1000, 1 /* screenRatio */, 0 /* padding */, ZERO_MARGIN, 0);
assertEquals(1, rects.size());
Rect singleRect = rects.get(0);
assertEquals(1000, singleRect.width());
}
+ @Test
public void testTwoTilesLandscape() {
List rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
- 2, 1200, 500, false /* allowLineOfThree */, 0 /* padding */);
+ 2, 1200, 500, 1.2f /* screenRatio */, 0 /* padding */, ZERO_MARGIN, 0);
assertEquals(2, rects.size());
for (Rect rect : rects) {
assertEquals(600, rect.width());
- assertEquals(500, rect.height());
+ assertEquals(499, rect.height());
}
}
+ @Test
public void testTwoTilesLandscapeWithPadding() {
List rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
- 2, 1200, 500, false /* allowLineOfThree */, 10 /* padding */);
+ 2, 1200, 500, 1.19f /* screenRatio */, 10 /* padding */, ZERO_MARGIN, 0);
assertEquals(2, rects.size());
Rect rectA = rects.get(0);
Rect rectB = rects.get(1);
@@ -60,46 +65,46 @@ public class TaskGridLayoutAlgorithmTest extends SysuiTestCase {
assertEquals(605, rectB.left);
}
+ @Test
public void testTwoTilesPortrait() {
List rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
- 2, 500, 1200, false /* allowLineOfThree */, 0 /* padding */);
+ 2, 500, 1200, 1 /* screenRatio */, 0 /* padding */, ZERO_MARGIN, 0);
assertEquals(2, rects.size());
for (Rect rect : rects) {
- assertEquals(500, rect.width());
- assertEquals(600, rect.height());
- }
- }
-
- public void testThreeTiles() {
- List rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
- 3, 1200, 500, false /* allowLineOfThree */, 0 /* padding */);
- assertEquals(3, rects.size());
- for (Rect rect : rects) {
- assertEquals(600, rect.width());
+ assertEquals(250, rect.width());
assertEquals(250, rect.height());
}
- // The third tile should be on the second line, in the middle.
- Rect rectC = rects.get(2);
- assertEquals(300, rectC.left);
- assertEquals(250, rectC.top);
}
+ @Test
+ public void testThreeTiles() {
+ List rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
+ 3, 1200, 500, 2 /* screenRatio */, 0 /* padding */, ZERO_MARGIN, 0);
+ assertEquals(3, rects.size());
+ for (Rect rect : rects) {
+ assertEquals(400, rect.width());
+ assertEquals(200, rect.height());
+ }
+ }
+
+ @Test
public void testFourTiles() {
List rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
- 4, 1200, 500, false /* allowLineOfThree */, 0 /* padding */);
+ 4, 1200, 500, 2.4f /* screenRatio */, 0 /* padding */, ZERO_MARGIN, 0);
assertEquals(4, rects.size());
for (Rect rect : rects) {
assertEquals(600, rect.width());
- assertEquals(250, rect.height());
+ assertEquals(249, rect.height());
}
Rect rectD = rects.get(3);
assertEquals(600, rectD.left);
assertEquals(250, rectD.top);
}
+ @Test
public void testNineTiles() {
List rects = TaskGridLayoutAlgorithm.getRectsForTaskCount(
- 9, 1200, 600, false /* allowLineOfThree */, 0 /* padding */);
+ 9, 1200, 600, 2 /* screenRatio */, 0 /* padding */, ZERO_MARGIN, 0);
assertEquals(9, rects.size());
for (Rect rect : rects) {
assertEquals(400, rect.width());