Updating task grouping logic.

- More fixes for graphical glitches when picking up task views.

Change-Id: I93fab1c2a9cc727c68d8f8fbd506bedaf681715f
This commit is contained in:
Winson Chung
2014-07-08 21:50:31 -07:00
parent 6057c91563
commit a433fa9c17
9 changed files with 97 additions and 86 deletions

View File

@@ -25,7 +25,7 @@
<com.android.systemui.recents.views.TaskBarView
android:id="@+id/task_view_bar"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_height="@dimen/recents_task_bar_height"
android:layout_gravity="top|center_horizontal"
android:background="@color/recents_task_bar_default_background_color">
<ImageView

View File

@@ -210,6 +210,9 @@
<!-- The amount of highlight to make on each task view. -->
<dimen name="recents_task_view_highlight">1dp</dimen>
<!-- The height of a task view bar. -->
<dimen name="recents_task_bar_height">56dp</dimen>
<!-- The height of the search bar space. -->
<dimen name="recents_search_bar_space_height">64dp</dimen>

View File

@@ -341,10 +341,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
}
// Get the transform for the running task
TaskStack.GroupTaskIndex groupTaskIndex = new TaskStack.GroupTaskIndex();
stack.getGroupIndexForTask(task, groupTaskIndex);
mTmpTransform = algo.getStackTransform(groupTaskIndex.groupIndex, groupTaskIndex.taskIndex,
tsv.getStackScroll(), mTmpTransform);
mTmpTransform = algo.getStackTransform(task, tsv.getStackScroll(), mTmpTransform);
mTmpTransform.rect.offset(mTaskStackBounds.left, mTaskStackBounds.top);
mTmpTransform.rect.offset(0, mStatusBarHeight);
return new Rect(mTmpTransform.rect);

View File

@@ -85,7 +85,8 @@ public class RecentsConfiguration {
public int taskBarViewDarkTextColor;
public int taskBarViewHighlightColor;
/** Task bar animations */
/** Task bar size & animations */
public int taskBarHeight;
public int taskBarEnterAnimDuration;
public int taskBarEnterAnimDelay;
public int taskBarExitAnimDuration;
@@ -214,7 +215,8 @@ public class RecentsConfiguration {
taskBarViewHighlightColor =
res.getColor(R.color.recents_task_bar_highlight_color);
// Task bar animations
// Task bar size & animations
taskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
taskBarEnterAnimDuration =
res.getInteger(R.integer.recents_animate_task_bar_enter_duration);
taskBarEnterAnimDelay =

View File

@@ -1,6 +1,7 @@
package com.android.systemui.recents.model;
import java.util.ArrayList;
import java.util.HashMap;
/** Represents a grouping of tasks witihin a stack. */
public class TaskGrouping {
@@ -9,6 +10,7 @@ public class TaskGrouping {
long latestActiveTimeInGroup;
ArrayList<Task.TaskKey> mTasks = new ArrayList<Task.TaskKey>();
HashMap<Task.TaskKey, Integer> mTaskIndices = new HashMap<Task.TaskKey, Integer>();
/** Creates a group with a specified affiliation. */
public TaskGrouping(String affiliation) {
@@ -22,6 +24,7 @@ public class TaskGrouping {
latestActiveTimeInGroup = t.key.lastActiveTime;
}
t.setGroup(this);
updateTaskIndices();
}
/** Removes a task from this group. */
@@ -36,6 +39,7 @@ public class TaskGrouping {
}
}
t.setGroup(null);
updateTaskIndices();
}
/** Gets the front task */
@@ -45,9 +49,19 @@ public class TaskGrouping {
/** Finds the index of a given task in a group. */
public int indexOf(Task t) {
return mTasks.indexOf(t.key);
return mTaskIndices.get(t.key);
}
/** Returns the number of tasks in this group. */
public int getTaskCount() { return mTasks.size(); }
/** Updates the mapping of tasks to indices. */
private void updateTaskIndices() {
mTaskIndices.clear();
int taskCount = mTasks.size();
for (int i = 0; i < taskCount; i++) {
Task.TaskKey k = mTasks.get(i);
mTaskIndices.put(k, i);
}
}
}

View File

@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
/**
@@ -174,7 +175,6 @@ public class TaskStack {
ArrayList<TaskGrouping> mGroups = new ArrayList<TaskGrouping>();
HashMap<String, TaskGrouping> mAffinitiesGroups = new HashMap<String, TaskGrouping>();
HashMap<TaskGrouping, Integer> mGroupsIndices = new HashMap<TaskGrouping, Integer>();
/** Sets the callbacks for this task stack */
public void setCallbacks(TaskStackCallbacks cb) {
@@ -295,23 +295,11 @@ public class TaskStack {
public void addGroup(TaskGrouping group) {
mGroups.add(group);
mAffinitiesGroups.put(group.affiliation, group);
updateTaskGroupingIndices();
}
public void removeGroup(TaskGrouping group) {
// XXX: Ensure that there are no more tasks in this group
mGroups.remove(group);
mAffinitiesGroups.remove(group.affiliation);
mGroupsIndices.remove(group);
updateTaskGroupingIndices();
}
/** Adds a mapping from a task to a group. */
public void addTaskToGroup(TaskGrouping group, Task task) {
if (!mAffinitiesGroups.containsKey(group.affiliation)) {
throw new RuntimeException("Unexpected group");
}
group.addTask(task);
}
/** Returns the group with the specified affiliation. */
@@ -319,17 +307,6 @@ public class TaskStack {
return mAffinitiesGroups.get(affiliation);
}
/** Returns the number of groups. */
public int getGroupingCount() {
return mGroups.size();
}
/** Returns the group and task indices for a given task. */
public void getGroupIndexForTask(Task task, GroupTaskIndex indices) {
indices.groupIndex = mGroupsIndices.get(task.group);
indices.taskIndex = task.group.indexOf(task);
}
/**
* Temporary: This method will simulate affiliation groups by
*/
@@ -349,18 +326,23 @@ public class TaskStack {
int taskCount = tasks.size();
String prevPackage = "";
String prevAffiliation = "";
Random r = new Random();
int groupCountDown = 1000;
for (int i = 0; i < taskCount; i++) {
Task t = tasks.get(i);
String packageName = t.key.baseIntent.getComponent().getPackageName();
packageName = "pkg";
TaskGrouping group;
if (packageName.equals(prevPackage)) {
if (packageName.equals(prevPackage) && groupCountDown > 0) {
group = getGroupWithAffiliation(prevAffiliation);
groupCountDown--;
} else {
String affiliation = counter.nextName();
group = new TaskGrouping(affiliation);
addGroup(group);
prevAffiliation = affiliation;
prevPackage = packageName;
groupCountDown = 1000;
}
group.addTask(t);
taskMap.put(t.key, t);
@@ -373,7 +355,6 @@ public class TaskStack {
taskGrouping2.latestActiveTimeInGroup);
}
});
updateTaskGroupingIndices();
// Sort group tasks by increasing firstActiveTime of the task, and also build a new list of
// tasks
int taskIndex = 0;
@@ -408,16 +389,6 @@ public class TaskStack {
}
}
/** Updates the mapping of tasks to indices. */
private void updateTaskGroupingIndices() {
mGroupsIndices.clear();
int groupsCount = mGroups.size();
for (int i = 0; i < groupsCount; i++) {
TaskGrouping g = mGroups.get(i);
mGroupsIndices.put(g, i);
}
}
@Override
public String toString() {
String str = "Tasks:\n";

View File

@@ -443,20 +443,16 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
int offsetX = 0;
int offsetY = 0;
int stackScroll = stackView.getStackScroll();
TaskStack.GroupTaskIndex groupTaskIndex = new TaskStack.GroupTaskIndex();
stack.getGroupIndexForTask(task, groupTaskIndex);
if (tv == null) {
// If there is no actual task view, then use the stack view as the source view
// and then offset to the expected transform rect, but bound this to just
// outside the display rect (to ensure we don't animate from too far away)
sourceView = stackView;
transform = stackView.getStackAlgorithm().getStackTransform(groupTaskIndex.groupIndex,
groupTaskIndex.taskIndex, stackScroll, transform);
transform = stackView.getStackAlgorithm().getStackTransform(task, stackScroll, transform);
offsetX = transform.rect.left;
offsetY = Math.min(transform.rect.top, mConfig.displayRect.height());
} else {
transform = stackView.getStackAlgorithm().getStackTransform(groupTaskIndex.groupIndex,
groupTaskIndex.taskIndex, stackScroll, transform);
transform = stackView.getStackAlgorithm().getStackTransform(task, stackScroll, transform);
}
// Compute the thumbnail to scale up from

View File

@@ -238,11 +238,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
// Update the stack transforms
TaskStack.GroupTaskIndex groupTaskIndex = new TaskStack.GroupTaskIndex();
for (int i = taskCount - 1; i >= 0; i--) {
mStack.getGroupIndexForTask(tasks.get(i), groupTaskIndex);
TaskViewTransform transform = mStackAlgorithm.getStackTransform(groupTaskIndex.groupIndex,
groupTaskIndex.taskIndex, stackScroll, taskTransforms.get(i));
TaskViewTransform transform = mStackAlgorithm.getStackTransform(tasks.get(i), stackScroll, taskTransforms.get(i));
if (transform.visible) {
if (frontMostVisibleIndex < 0) {
frontMostVisibleIndex = i;
@@ -332,14 +329,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
if (mStackViewsAnimationDuration > 0) {
// For items in the list, put them in start animating them from the
// approriate ends of the list where they are expected to appear
Task fromTask = (transform.t < 0) ?
tasks.get(visibleRange[1]) :
tasks.get(visibleRange[0]);
mStack.getGroupIndexForTask(fromTask, gti);
tmpTransform = mStackAlgorithm.getStackTransform(
(transform.t < 0) ? gti.groupIndex - 1 : gti.groupIndex + 1,
(transform.t < 0) ? gti.taskIndex - 1 : gti.taskIndex + 1,
stackScroll, tmpTransform);
if (transform.t < 0) {
tmpTransform = mStackAlgorithm.getStackTransform(tasks.get(0), stackScroll, tmpTransform);
} else {
tmpTransform = mStackAlgorithm.getStackTransform(tasks.get(Math.min(tasks.size() - 1, visibleRange[0] + 1)),
stackScroll, tmpTransform);
}
tv.updateViewPropertiesToTaskTransform(tmpTransform, 0);
}
}
@@ -376,7 +371,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
/** Computes the initial stack scroll for the stack. */
int getInitialStackScroll() {
if (mStack.getGroupingCount() > 2) {
if (mStack.getTaskCount() > 2) {
return mMaxScroll - mStackAlgorithm.mTaskRect.height() / 2;
}
return mMaxScroll;
@@ -496,7 +491,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/** Updates the min and max virtual scroll bounds */
void updateMinMaxScroll(boolean boundScrollToNewMinMax) {
// Compute the min and max scroll values
mStackAlgorithm.computeMinMaxScroll(mStack.getGroupingCount());
mStackAlgorithm.computeMinMaxScroll(mStack.getTasks());
mMinScroll = mStackAlgorithm.mMinScroll;
mMaxScroll = mStackAlgorithm.mMaxScroll;
@@ -562,7 +557,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
if (scrollToNewPosition) {
// Scroll the view into position
int newScroll = Math.max(mMinScroll, Math.min(mMaxScroll,
mStackAlgorithm.getStackScrollForTaskIndex(taskIndex)));
mStackAlgorithm.getStackScrollForTaskIndex(t)));
animateScroll(getStackScroll(), newScroll, postScrollRunnable);
} else {
@@ -692,7 +687,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/** Computes the stack and task rects */
public void computeRects(int width, int height, int insetLeft, int insetBottom) {
// Compute the rects in the stack algorithm
mStackAlgorithm.computeRects(width, height, insetLeft, insetBottom);
mStackAlgorithm.computeRects(mStack.getTasks(), width, height, insetLeft, insetBottom);
// Update the scroll bounds
updateMinMaxScroll(false);
@@ -814,8 +809,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
if (mStack.getTaskCount() > 0) {
TaskStack.GroupTaskIndex groupTaskIndex = new TaskStack.GroupTaskIndex();
if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
// Find the target task with the specified id
ArrayList<Task> tasks = mStack.getTasks();
@@ -834,10 +827,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Find the group and task index of the target task
if (targetTask != null) {
mStack.getGroupIndexForTask(targetTask, groupTaskIndex);
ctx.targetTaskTransform = new TaskViewTransform();
mStackAlgorithm.getStackTransform(groupTaskIndex.groupIndex,
groupTaskIndex.taskIndex, getStackScroll(), ctx.targetTaskTransform);
mStackAlgorithm.getStackTransform(targetTask, getStackScroll(), ctx.targetTaskTransform);
Rect taskStackBounds = new Rect();
mConfig.getTaskStackBounds(getMeasuredWidth(), getMeasuredHeight(), taskStackBounds);
ctx.targetTaskTransform.rect.offset(taskStackBounds.left, taskStackBounds.top);
@@ -852,9 +843,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
ctx.currentStackViewIndex = i;
ctx.currentStackViewCount = childCount;
ctx.isCurrentTaskFrontMost = (i == (getChildCount() - 1));
mStack.getGroupIndexForTask(tv.getTask(), groupTaskIndex);
mStackAlgorithm.getStackTransform(groupTaskIndex.groupIndex, groupTaskIndex.taskIndex,
getStackScroll(), ctx.currentTaskTransform);
mStackAlgorithm.getStackTransform(tv.getTask(), getStackScroll(), ctx.currentTaskTransform);
tv.startEnterRecentsAnimation(ctx);
}
@@ -909,11 +898,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
@Override
public void onStackTaskAdded(TaskStack stack, Task t) {
// Update the task offsets
mStackAlgorithm.updateTaskOffsets(mStack.getTasks());
requestSynchronizeStackViewsWithModel();
}
@Override
public void onStackTaskRemoved(TaskStack stack, Task t) {
// Update the task offsets
mStackAlgorithm.updateTaskOffsets(mStack.getTasks());
// Remove the view associated with this task, we can't rely on updateTransforms
// to work here because the task is no longer in the list
TaskView tv = getChildViewForTask(t);
@@ -953,6 +948,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
ArrayList<TaskViewTransform> curTaskTransforms =
getStackTransforms(curTasks, getStackScroll(), null, true);
// Update the task offsets
mStackAlgorithm.updateTaskOffsets(mStack.getTasks());
// Scroll the item to the top of the stack (sans-peek) rect so that we can see it better
updateMinMaxScroll(false);
float overlapHeight = mStackAlgorithm.getTaskOverlapHeight();
@@ -977,6 +975,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
final ArrayList<TaskViewTransform> curTaskTransforms =
getStackTransforms(curTasks, getStackScroll(), null, true);
// Update the task offsets
mStackAlgorithm.updateTaskOffsets(mStack.getTasks());
// Restore the stashed scroll
updateMinMaxScroll(false);
setStackScrollRaw(mStashedScroll);

View File

@@ -20,6 +20,10 @@ 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;
import java.util.ArrayList;
import java.util.HashMap;
/* The layout logic for a TaskStackView */
public class TaskStackViewLayoutAlgorithm {
@@ -42,12 +46,14 @@ public class TaskStackViewLayoutAlgorithm {
int mMinScroll;
int mMaxScroll;
HashMap<Task.TaskKey, Integer> mTaskOffsetMap = new HashMap<Task.TaskKey, Integer>();
public TaskStackViewLayoutAlgorithm(RecentsConfiguration config) {
mConfig = config;
}
/** Computes the stack and task rects */
public void computeRects(int width, int height, int insetLeft, int insetBottom) {
public void computeRects(ArrayList<Task> tasks, int width, int height, int insetLeft, int insetBottom) {
// 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
@@ -76,29 +82,31 @@ public class TaskStackViewLayoutAlgorithm {
int left = mStackRect.left + (mStackRect.width() - size) / 2;
mTaskRect.set(left, mStackRectSansPeek.top,
left + size, mStackRectSansPeek.top + size);
// Update the task offsets once the size changes
updateTaskOffsets(tasks);
}
void computeMinMaxScroll(int taskCount) {
void computeMinMaxScroll(ArrayList<Task> tasks) {
// Compute the min and max scroll values
int numTasks = Math.max(1, taskCount);
int numTasks = Math.max(1, tasks.size());
int taskHeight = mTaskRect.height();
int stackHeight = mStackRectSansPeek.height();
int maxScrollHeight = taskHeight + getStackScrollForTaskIndex(numTasks - 1);
if (numTasks <= 1) {
// If there is only one task, then center the task in the stack rect (sans peek)
mMinScroll = mMaxScroll = -(stackHeight - taskHeight) / 2;
} else {
int maxScrollHeight = taskHeight + getStackScrollForTaskIndex(tasks.get(tasks.size() - 1));
mMinScroll = Math.min(stackHeight, maxScrollHeight) - stackHeight;
mMaxScroll = maxScrollHeight - stackHeight;
}
}
/** Update/get the transform */
public TaskViewTransform getStackTransform(int groupIndexInStack, int taskIndexInGroup,
int stackScroll, TaskViewTransform transformOut) {
public TaskViewTransform getStackTransform(Task task, int stackScroll, TaskViewTransform transformOut) {
// Return early if we have an invalid index
if (groupIndexInStack < 0) {
if (task == null) {
transformOut.reset();
return transformOut;
}
@@ -107,7 +115,7 @@ public class TaskStackViewLayoutAlgorithm {
int numPeekCards = StackPeekNumCards;
float overlapHeight = StackOverlapPct * mTaskRect.height();
float peekHeight = StackPeekHeightPct * mStackRect.height();
float t = ((groupIndexInStack * overlapHeight) - stackScroll) / overlapHeight;
float t = (getStackScrollForTaskIndex(task) - stackScroll) / overlapHeight;
float boundedT = Math.max(t, -(numPeekCards + 1));
// Set the scale relative to its position
@@ -118,6 +126,8 @@ public class TaskStackViewLayoutAlgorithm {
float scale = Math.max(minScale, Math.min(1f, minScale +
((boundedT + (numPeekCards + 1)) * scaleInc)));
float scaleYOffset = ((1f - scale) * mTaskRect.height()) / 2;
// Account for the bar offsets being scaled?
float scaleBarYOffset = (1f - scale) * mConfig.taskBarHeight;
transformOut.scale = scale;
// Set the y translation
@@ -125,9 +135,8 @@ public class TaskStackViewLayoutAlgorithm {
transformOut.translationY = (int) ((Math.max(-numPeekCards, boundedT) /
numPeekCards) * peekHeight - scaleYOffset);
} else {
transformOut.translationY = (int) (boundedT * overlapHeight - scaleYOffset);
transformOut.translationY = (int) (boundedT * overlapHeight - scaleYOffset - scaleBarYOffset);
}
transformOut.translationY += 100 * taskIndexInGroup;
// Set the z translation
int minZ = mConfig.taskViewTranslationZMinPx;
@@ -161,8 +170,26 @@ public class TaskStackViewLayoutAlgorithm {
* Returns the scroll to such that the task transform at that index will have t=0. (If the scroll
* is not bounded)
*/
int getStackScrollForTaskIndex(int i) {
return (int) (i * getTaskOverlapHeight());
int getStackScrollForTaskIndex(Task t) {
return mTaskOffsetMap.get(t.key);
}
/**
* Updates the cache of tasks to offsets.
*/
void updateTaskOffsets(ArrayList<Task> tasks) {
mTaskOffsetMap.clear();
int offset = 0;
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
Task t = tasks.get(i);
mTaskOffsetMap.put(t.key, offset);
if (t.group.isFrontMostTask(t)) {
offset += getTaskOverlapHeight();
} else {
offset += mConfig.taskBarHeight;
}
}
}
}