Merge "Enabling filtering by base intent package."
This commit is contained in:
@@ -26,7 +26,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="top|center_horizontal"
|
android:layout_gravity="top|center_horizontal"
|
||||||
android:background="#88000000">
|
android:background="#e6444444">
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/activity_icon"
|
android:id="@+id/activity_icon"
|
||||||
android:layout_width="@dimen/recents_task_view_icon_size"
|
android:layout_width="@dimen/recents_task_view_icon_size"
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class Constants {
|
|||||||
public static final boolean Verbose = false;
|
public static final boolean Verbose = false;
|
||||||
|
|
||||||
public static class App {
|
public static class App {
|
||||||
public static final boolean EnableTaskFiltering = false;
|
public static final boolean EnableTaskFiltering = true;
|
||||||
public static final boolean EnableTaskStackClipping = false;
|
public static final boolean EnableTaskStackClipping = false;
|
||||||
public static final boolean EnableToggleNewRecentsActivity = false;
|
public static final boolean EnableToggleNewRecentsActivity = false;
|
||||||
// This disables the bitmap and icon caches to
|
// This disables the bitmap and icon caches to
|
||||||
@@ -81,6 +81,10 @@ public class Constants {
|
|||||||
public static class Animation {
|
public static class Animation {
|
||||||
public static final int TaskRemovedReshuffleDuration = 200;
|
public static final int TaskRemovedReshuffleDuration = 200;
|
||||||
public static final int SnapScrollBackDuration = 650;
|
public static final int SnapScrollBackDuration = 650;
|
||||||
|
public static final int FilteredCurrentViewsDuration = 150;
|
||||||
|
public static final int FilteredNewViewsDuration = 200;
|
||||||
|
public static final int UnfilteredCurrentViewsDuration = 150;
|
||||||
|
public static final int UnfilteredNewViewsDuration = 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final int TaskStackOverscrollRange = 150;
|
public static final int TaskStackOverscrollRange = 150;
|
||||||
@@ -107,7 +111,7 @@ public class Constants {
|
|||||||
public static final boolean AnimateFrontTaskIconOnEnterRecents = true;
|
public static final boolean AnimateFrontTaskIconOnEnterRecents = true;
|
||||||
public static final boolean AnimateFrontTaskIconOnLeavingRecents = true;
|
public static final boolean AnimateFrontTaskIconOnLeavingRecents = true;
|
||||||
|
|
||||||
public static final boolean UseRoundedCorners = true;
|
public static final boolean UseRoundedCorners = false;
|
||||||
public static final float RoundedCornerRadiusDps = 3;
|
public static final float RoundedCornerRadiusDps = 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,8 +54,11 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
|
|||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
} else if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
|
} else if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
|
||||||
// Dismiss recents and launch the first task if possible
|
// Try and unfilter and filtered stacks
|
||||||
dismissRecentsIfVisible();
|
if (!mRecentsView.unfilterFilteredStacks()) {
|
||||||
|
// If there are no filtered stacks, dismiss recents and launch the first task
|
||||||
|
dismissRecentsIfVisible();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ class SystemUIMessageHandler extends Handler {
|
|||||||
// in a bottom inset
|
// in a bottom inset
|
||||||
tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top, 0);
|
tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top, 0);
|
||||||
tsv.boundScroll();
|
tsv.boundScroll();
|
||||||
TaskViewTransform transform = tsv.getStackTransform(0);
|
TaskViewTransform transform = tsv.getStackTransform(0, tsv.getStackScroll());
|
||||||
Rect taskRect = new Rect(transform.rect);
|
Rect taskRect = new Rect(transform.rect);
|
||||||
|
|
||||||
data.putParcelable("taskRect", taskRect);
|
data.putParcelable("taskRect", taskRect);
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ class TaskResourceLoader implements Runnable {
|
|||||||
// Load the icon
|
// Load the icon
|
||||||
if (loadIcon == null || forceLoadTask) {
|
if (loadIcon == null || forceLoadTask) {
|
||||||
PackageManager pm = mContext.getPackageManager();
|
PackageManager pm = mContext.getPackageManager();
|
||||||
ActivityInfo info = pm.getActivityInfo(t.key.intent.getComponent(),
|
ActivityInfo info = pm.getActivityInfo(t.key.baseIntent.getComponent(),
|
||||||
PackageManager.GET_META_DATA);
|
PackageManager.GET_META_DATA);
|
||||||
Drawable icon = info.loadIcon(pm);
|
Drawable icon = info.loadIcon(pm);
|
||||||
if (!mCancelled) {
|
if (!mCancelled) {
|
||||||
@@ -218,7 +218,7 @@ class TaskResourceLoader implements Runnable {
|
|||||||
} else {
|
} else {
|
||||||
Console.logError(mContext,
|
Console.logError(mContext,
|
||||||
"Failed to load task top thumbnail for: " +
|
"Failed to load task top thumbnail for: " +
|
||||||
t.key.intent.getComponent().getPackageName());
|
t.key.baseIntent.getComponent().getPackageName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,9 +20,6 @@ import android.graphics.Rect;
|
|||||||
|
|
||||||
/* Common code */
|
/* Common code */
|
||||||
public class Utilities {
|
public class Utilities {
|
||||||
public static final Rect tmpRect = new Rect();
|
|
||||||
public static final Rect tmpRect2 = new Rect();
|
|
||||||
|
|
||||||
/** Scales a rect about its centroid */
|
/** Scales a rect about its centroid */
|
||||||
public static void scaleRectAboutCenter(Rect r, float scale) {
|
public static void scaleRectAboutCenter(Rect r, float scale) {
|
||||||
if (scale != 1.0f) {
|
if (scale != 1.0f) {
|
||||||
|
|||||||
@@ -37,11 +37,11 @@ public class Task {
|
|||||||
/* The Task Key represents the unique primary key for the task */
|
/* The Task Key represents the unique primary key for the task */
|
||||||
public static class TaskKey {
|
public static class TaskKey {
|
||||||
public final int id;
|
public final int id;
|
||||||
public final Intent intent;
|
public final Intent baseIntent;
|
||||||
|
|
||||||
public TaskKey(int id, Intent intent) {
|
public TaskKey(int id, Intent intent) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.intent = intent;
|
this.baseIntent = intent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -56,7 +56,7 @@ public class Task {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Task.Key: " + id + ", " + intent.getComponent().getPackageName();
|
return "Task.Key: " + id + ", " + baseIntent.getComponent().getPackageName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,6 +120,6 @@ public class Task {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Task: " + key.intent.getComponent().getPackageName() + " [" + super.toString() + "]";
|
return "Task: " + key.baseIntent.getComponent().getPackageName() + " [" + super.toString() + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,9 +39,11 @@ class FilteredTaskList {
|
|||||||
TaskFilter mFilter;
|
TaskFilter mFilter;
|
||||||
|
|
||||||
/** Sets the task filter, saving the current touch state */
|
/** Sets the task filter, saving the current touch state */
|
||||||
void setFilter(TaskFilter filter) {
|
boolean setFilter(TaskFilter filter) {
|
||||||
|
ArrayList<Task> prevFilteredTasks = new ArrayList<Task>(mFilteredTasks);
|
||||||
mFilter = filter;
|
mFilter = filter;
|
||||||
updateFilteredTasks();
|
updateFilteredTasks();
|
||||||
|
return !prevFilteredTasks.equals(mFilteredTasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Removes the task filter and returns the previous touch state */
|
/** Removes the task filter and returns the previous touch state */
|
||||||
@@ -126,9 +128,9 @@ public class TaskStack {
|
|||||||
/* Notifies when a task has been removed from the stack */
|
/* Notifies when a task has been removed from the stack */
|
||||||
public void onStackTaskRemoved(TaskStack stack, Task t);
|
public void onStackTaskRemoved(TaskStack stack, Task t);
|
||||||
/** Notifies when the stack was filtered */
|
/** Notifies when the stack was filtered */
|
||||||
public void onStackFiltered(TaskStack stack);
|
public void onStackFiltered(TaskStack newStack, ArrayList<Task> curStack, Task t);
|
||||||
/** Notifies when the stack was un-filtered */
|
/** Notifies when the stack was un-filtered */
|
||||||
public void onStackUnfiltered(TaskStack stack);
|
public void onStackUnfiltered(TaskStack newStack, ArrayList<Task> curStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
Context mContext;
|
Context mContext;
|
||||||
@@ -201,29 +203,30 @@ public class TaskStack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Filters the stack into tasks similar to the one specified */
|
/** Filters the stack into tasks similar to the one specified */
|
||||||
public void filterTasks(Task t) {
|
public void filterTasks(final Task t) {
|
||||||
|
ArrayList<Task> oldStack = new ArrayList<Task>(mTaskList.getTasks());
|
||||||
|
|
||||||
// Set the task list filter
|
// Set the task list filter
|
||||||
// XXX: This is a dummy filter that currently just accepts every other task.
|
boolean filtered = mTaskList.setFilter(new TaskFilter() {
|
||||||
mTaskList.setFilter(new TaskFilter() {
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptTask(Task t, int i) {
|
public boolean acceptTask(Task at, int i) {
|
||||||
if (i % 2 == 0) {
|
return t.key.baseIntent.getComponent().getPackageName().equals(
|
||||||
return true;
|
at.key.baseIntent.getComponent().getPackageName());
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (mCb != null) {
|
if (filtered && mCb != null) {
|
||||||
mCb.onStackFiltered(this);
|
mCb.onStackFiltered(this, oldStack, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Unfilters the current stack */
|
/** Unfilters the current stack */
|
||||||
public void unfilterTasks() {
|
public void unfilterTasks() {
|
||||||
|
ArrayList<Task> oldStack = new ArrayList<Task>(mTaskList.getTasks());
|
||||||
|
|
||||||
// Unset the filter, then update the virtual scroll
|
// Unset the filter, then update the virtual scroll
|
||||||
mTaskList.removeFilter();
|
mTaskList.removeFilter();
|
||||||
if (mCb != null) {
|
if (mCb != null) {
|
||||||
mCb.onStackUnfiltered(this);
|
mCb.onStackUnfiltered(this, oldStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -211,17 +211,18 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
|
|||||||
View sourceView = tv;
|
View sourceView = tv;
|
||||||
int offsetX = 0;
|
int offsetX = 0;
|
||||||
int offsetY = 0;
|
int offsetY = 0;
|
||||||
|
int stackScroll = stackView.getStackScroll();
|
||||||
if (tv == null) {
|
if (tv == null) {
|
||||||
// If there is no actual task view, then use the stack view as the source view
|
// 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
|
// 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)
|
// outside the display rect (to ensure we don't animate from too far away)
|
||||||
RecentsConfiguration config = RecentsConfiguration.getInstance();
|
RecentsConfiguration config = RecentsConfiguration.getInstance();
|
||||||
sourceView = stackView;
|
sourceView = stackView;
|
||||||
transform = stackView.getStackTransform(stack.indexOfTask(task));
|
transform = stackView.getStackTransform(stack.indexOfTask(task), stackScroll);
|
||||||
offsetX = transform.rect.left;
|
offsetX = transform.rect.left;
|
||||||
offsetY = Math.min(transform.rect.top, config.displayRect.height());
|
offsetY = Math.min(transform.rect.top, config.displayRect.height());
|
||||||
} else {
|
} else {
|
||||||
transform = stackView.getStackTransform(stack.indexOfTask(task));
|
transform = stackView.getStackTransform(stack.indexOfTask(task), stackScroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the thumbnail to scale up from
|
// Compute the thumbnail to scale up from
|
||||||
@@ -255,7 +256,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Launch the activity with the desired animation
|
// Launch the activity with the desired animation
|
||||||
Intent i = new Intent(task.key.intent);
|
Intent i = new Intent(task.key.baseIntent);
|
||||||
i.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
|
i.setFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
|
||||||
| Intent.FLAG_ACTIVITY_TASK_ON_HOME
|
| Intent.FLAG_ACTIVITY_TASK_ON_HOME
|
||||||
| Intent.FLAG_ACTIVITY_NEW_TASK);
|
| Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.systemui.recents.views;
|
|||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
|
import android.animation.AnimatorSet;
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
@@ -34,6 +35,7 @@ import android.view.ViewConfiguration;
|
|||||||
import android.view.ViewParent;
|
import android.view.ViewParent;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.OverScroller;
|
import android.widget.OverScroller;
|
||||||
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.recents.Console;
|
import com.android.systemui.recents.Console;
|
||||||
import com.android.systemui.recents.Constants;
|
import com.android.systemui.recents.Constants;
|
||||||
import com.android.systemui.recents.RecentsConfiguration;
|
import com.android.systemui.recents.RecentsConfiguration;
|
||||||
@@ -41,7 +43,6 @@ import com.android.systemui.recents.RecentsTaskLoader;
|
|||||||
import com.android.systemui.recents.Utilities;
|
import com.android.systemui.recents.Utilities;
|
||||||
import com.android.systemui.recents.model.Task;
|
import com.android.systemui.recents.model.Task;
|
||||||
import com.android.systemui.recents.model.TaskStack;
|
import com.android.systemui.recents.model.TaskStack;
|
||||||
import com.android.systemui.R;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
@@ -71,6 +72,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
int mStackScroll;
|
int mStackScroll;
|
||||||
int mMinScroll;
|
int mMinScroll;
|
||||||
int mMaxScroll;
|
int mMaxScroll;
|
||||||
|
int mStashedScroll;
|
||||||
OverScroller mScroller;
|
OverScroller mScroller;
|
||||||
ObjectAnimator mScrollAnimator;
|
ObjectAnimator mScrollAnimator;
|
||||||
|
|
||||||
@@ -79,6 +81,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
int mStackViewsAnimationDuration;
|
int mStackViewsAnimationDuration;
|
||||||
boolean mStackViewsDirty = true;
|
boolean mStackViewsDirty = true;
|
||||||
boolean mAwaitingFirstLayout = true;
|
boolean mAwaitingFirstLayout = true;
|
||||||
|
int[] mTmpVisibleRange = new int[2];
|
||||||
|
Rect mTmpRect = new Rect();
|
||||||
|
Rect mTmpRect2 = new Rect();
|
||||||
LayoutInflater mInflater;
|
LayoutInflater mInflater;
|
||||||
|
|
||||||
public TaskStackView(Context context, TaskStack stack) {
|
public TaskStackView(Context context, TaskStack stack) {
|
||||||
@@ -102,7 +107,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
}
|
}
|
||||||
void requestSynchronizeStackViewsWithModel(int duration) {
|
void requestSynchronizeStackViewsWithModel(int duration) {
|
||||||
Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
|
Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
|
||||||
"[TaskStackView|requestSynchronize]", "", Console.AnsiYellow);
|
"[TaskStackView|requestSynchronize]", "" + duration + "ms", Console.AnsiYellow);
|
||||||
if (!mStackViewsDirty) {
|
if (!mStackViewsDirty) {
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
@@ -128,14 +133,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Update/get the transform */
|
/** Update/get the transform */
|
||||||
public TaskViewTransform getStackTransform(int indexInStack) {
|
public TaskViewTransform getStackTransform(int indexInStack, int stackScroll) {
|
||||||
TaskViewTransform transform = new TaskViewTransform();
|
TaskViewTransform transform = new TaskViewTransform();
|
||||||
|
|
||||||
// Map the items to an continuous position relative to the current scroll
|
// Return early if we have an invalid index
|
||||||
|
if (indexInStack < 0) return transform;
|
||||||
|
|
||||||
|
// Map the items to an continuous position relative to the specified scroll
|
||||||
int numPeekCards = Constants.Values.TaskStackView.StackPeekNumCards;
|
int numPeekCards = Constants.Values.TaskStackView.StackPeekNumCards;
|
||||||
float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
|
float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
|
||||||
float peekHeight = Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height();
|
float peekHeight = Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height();
|
||||||
float t = ((indexInStack * overlapHeight) - getStackScroll()) / overlapHeight;
|
float t = ((indexInStack * overlapHeight) - stackScroll) / overlapHeight;
|
||||||
float boundedT = Math.max(t, -(numPeekCards + 1));
|
float boundedT = Math.max(t, -(numPeekCards + 1));
|
||||||
|
|
||||||
// Set the scale relative to its position
|
// Set the scale relative to its position
|
||||||
@@ -167,25 +175,57 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
return transform;
|
return transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the stack transforms of a list of tasks, and returns the visible range of tasks.
|
||||||
|
*/
|
||||||
|
private ArrayList<TaskViewTransform> getStackTransforms(ArrayList<Task> tasks,
|
||||||
|
int stackScroll,
|
||||||
|
int[] visibleRangeOut) {
|
||||||
|
// XXX: Optimization: Use binary search to find the visible range
|
||||||
|
|
||||||
|
ArrayList<TaskViewTransform> taskTransforms = new ArrayList<TaskViewTransform>();
|
||||||
|
int taskCount = tasks.size();
|
||||||
|
int firstVisibleIndex = -1;
|
||||||
|
int lastVisibleIndex = -1;
|
||||||
|
for (int i = 0; i < taskCount; i++) {
|
||||||
|
TaskViewTransform transform = getStackTransform(i, stackScroll);
|
||||||
|
taskTransforms.add(transform);
|
||||||
|
if (transform.visible) {
|
||||||
|
if (firstVisibleIndex < 0) {
|
||||||
|
firstVisibleIndex = i;
|
||||||
|
}
|
||||||
|
lastVisibleIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (visibleRangeOut != null) {
|
||||||
|
visibleRangeOut[0] = firstVisibleIndex;
|
||||||
|
visibleRangeOut[1] = lastVisibleIndex;
|
||||||
|
}
|
||||||
|
return taskTransforms;
|
||||||
|
}
|
||||||
|
|
||||||
/** Synchronizes the views with the model */
|
/** Synchronizes the views with the model */
|
||||||
void synchronizeStackViewsWithModel() {
|
void synchronizeStackViewsWithModel() {
|
||||||
Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
|
Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
|
||||||
"[TaskStackView|synchronizeViewsWithModel]",
|
"[TaskStackView|synchronizeViewsWithModel]",
|
||||||
"mStackViewsDirty: " + mStackViewsDirty, Console.AnsiYellow);
|
"mStackViewsDirty: " + mStackViewsDirty, Console.AnsiYellow);
|
||||||
if (mStackViewsDirty) {
|
if (mStackViewsDirty) {
|
||||||
|
|
||||||
// XXX: Optimization: Use binary search to find the visible range
|
|
||||||
// XXX: Optimize to not call getStackTransform() so many times
|
|
||||||
// XXX: Consider using TaskViewTransform pool to prevent allocations
|
// XXX: Consider using TaskViewTransform pool to prevent allocations
|
||||||
// XXX: Iterate children views, update transforms and remove all that are not visible
|
// XXX: Iterate children views, update transforms and remove all that are not visible
|
||||||
// For all remaining tasks, update transforms and if visible add the view
|
// For all remaining tasks, update transforms and if visible add the view
|
||||||
|
|
||||||
// Update the visible state of all the tasks
|
// Get all the task transforms
|
||||||
|
int[] visibleRange = mTmpVisibleRange;
|
||||||
|
int stackScroll = getStackScroll();
|
||||||
ArrayList<Task> tasks = mStack.getTasks();
|
ArrayList<Task> tasks = mStack.getTasks();
|
||||||
|
ArrayList<TaskViewTransform> taskTransforms = getStackTransforms(tasks, stackScroll,
|
||||||
|
visibleRange);
|
||||||
|
|
||||||
|
// Update the visible state of all the tasks
|
||||||
int taskCount = tasks.size();
|
int taskCount = tasks.size();
|
||||||
for (int i = 0; i < taskCount; i++) {
|
for (int i = 0; i < taskCount; i++) {
|
||||||
Task task = tasks.get(i);
|
Task task = tasks.get(i);
|
||||||
TaskViewTransform transform = getStackTransform(i);
|
TaskViewTransform transform = taskTransforms.get(i);
|
||||||
TaskView tv = getChildViewForTask(task);
|
TaskView tv = getChildViewForTask(task);
|
||||||
|
|
||||||
if (transform.visible) {
|
if (transform.visible) {
|
||||||
@@ -194,11 +234,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
// When we are picking up a new view from the view pool, prepare it for any
|
// When we are picking up a new view from the view pool, prepare it for any
|
||||||
// following animation by putting it in a reasonable place
|
// following animation by putting it in a reasonable place
|
||||||
if (mStackViewsAnimationDuration > 0 && i != 0) {
|
if (mStackViewsAnimationDuration > 0 && i != 0) {
|
||||||
// XXX: We have to animate when filtering, etc. Maybe we should have a
|
|
||||||
// runnable that ensures that tasks are animated in a special way
|
|
||||||
// when they are entering the scene?
|
|
||||||
int fromIndex = (transform.t < 0) ? (i - 1) : (i + 1);
|
int fromIndex = (transform.t < 0) ? (i - 1) : (i + 1);
|
||||||
tv.updateViewPropertiesFromTask(null, getStackTransform(fromIndex), 0);
|
tv.updateViewPropertiesToTaskTransform(null,
|
||||||
|
getStackTransform(fromIndex, stackScroll), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -208,17 +246,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update all the current view children
|
// Update all the remaining view children
|
||||||
// NOTE: We have to iterate in reverse where because we are removing views directly
|
// NOTE: We have to iterate in reverse where because we are removing views directly
|
||||||
int childCount = getChildCount();
|
int childCount = getChildCount();
|
||||||
for (int i = childCount - 1; i >= 0; i--) {
|
for (int i = childCount - 1; i >= 0; i--) {
|
||||||
TaskView tv = (TaskView) getChildAt(i);
|
TaskView tv = (TaskView) getChildAt(i);
|
||||||
Task task = tv.getTask();
|
Task task = tv.getTask();
|
||||||
TaskViewTransform transform = getStackTransform(mStack.indexOfTask(task));
|
int taskIndex = mStack.indexOfTask(task);
|
||||||
if (!transform.visible) {
|
if (taskIndex < 0 || !taskTransforms.get(taskIndex).visible) {
|
||||||
mViewPool.returnViewToPool(tv);
|
mViewPool.returnViewToPool(tv);
|
||||||
} else {
|
} else {
|
||||||
tv.updateViewPropertiesFromTask(null, transform, mStackViewsAnimationDuration);
|
tv.updateViewPropertiesToTaskTransform(null, taskTransforms.get(taskIndex),
|
||||||
|
mStackViewsAnimationDuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,6 +274,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
mStackScroll = value;
|
mStackScroll = value;
|
||||||
requestSynchronizeStackViewsWithModel();
|
requestSynchronizeStackViewsWithModel();
|
||||||
}
|
}
|
||||||
|
/** Sets the current stack scroll without synchronizing the stack view with the model */
|
||||||
|
public void setStackScrollRaw(int value) {
|
||||||
|
mStackScroll = value;
|
||||||
|
}
|
||||||
|
|
||||||
/** Gets the current stack scroll */
|
/** Gets the current stack scroll */
|
||||||
public int getStackScroll() {
|
public int getStackScroll() {
|
||||||
@@ -251,36 +294,39 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
|
|
||||||
// Abort any current animations
|
// Abort any current animations
|
||||||
abortScroller();
|
abortScroller();
|
||||||
if (mScrollAnimator != null) {
|
abortBoundScrollAnimation();
|
||||||
mScrollAnimator.cancel();
|
|
||||||
mScrollAnimator.removeAllListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start a new scroll animation
|
// Start a new scroll animation
|
||||||
mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
|
animateScroll(curScroll, newScroll, duration);
|
||||||
mScrollAnimator.setDuration(duration);
|
|
||||||
mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationUpdate(ValueAnimator animation) {
|
|
||||||
setStackScroll((Integer) animation.getAnimatedValue());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mScrollAnimator.addListener(new AnimatorListenerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation) {
|
|
||||||
// Disable hw layers on the stack
|
|
||||||
decHwLayersRefCount("animateBoundScroll");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mScrollAnimator.start();
|
mScrollAnimator.start();
|
||||||
}
|
}
|
||||||
return mScrollAnimator;
|
return mScrollAnimator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Animates the stack scroll */
|
||||||
|
void animateScroll(int curScroll, int newScroll, int duration) {
|
||||||
|
mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
|
||||||
|
mScrollAnimator.setDuration(duration);
|
||||||
|
mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationUpdate(ValueAnimator animation) {
|
||||||
|
setStackScroll((Integer) animation.getAnimatedValue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
mScrollAnimator.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
// Disable hw layers on the stack
|
||||||
|
decHwLayersRefCount("animateBoundScroll");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** Aborts any current stack scrolls */
|
/** Aborts any current stack scrolls */
|
||||||
void abortBoundScrollAnimation() {
|
void abortBoundScrollAnimation() {
|
||||||
if (mScrollAnimator != null) {
|
if (mScrollAnimator != null) {
|
||||||
mScrollAnimator.cancel();
|
mScrollAnimator.cancel();
|
||||||
|
mScrollAnimator.removeAllListeners();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,6 +350,20 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bounds the current scroll if necessary, but does not synchronize the stack view with the
|
||||||
|
* model.
|
||||||
|
*/
|
||||||
|
public boolean boundScrollRaw() {
|
||||||
|
int curScroll = getStackScroll();
|
||||||
|
int newScroll = Math.max(mMinScroll, Math.min(mMaxScroll, curScroll));
|
||||||
|
if (newScroll != curScroll) {
|
||||||
|
setStackScrollRaw(newScroll);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns whether the current scroll is out of bounds */
|
/** Returns whether the current scroll is out of bounds */
|
||||||
boolean isScrollOutOfBounds() {
|
boolean isScrollOutOfBounds() {
|
||||||
return (getStackScroll() < 0) || (getStackScroll() > mMaxScroll);
|
return (getStackScroll() < 0) || (getStackScroll() > mMaxScroll);
|
||||||
@@ -404,12 +464,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
TaskView tv = (TaskView) child;
|
TaskView tv = (TaskView) child;
|
||||||
TaskView nextTv = null;
|
TaskView nextTv = null;
|
||||||
int curIndex = indexOfChild(tv);
|
int curIndex = indexOfChild(tv);
|
||||||
if (curIndex < (getChildCount() - 1)) {
|
if ((curIndex > -1) && (curIndex < (getChildCount() - 1))) {
|
||||||
// Clip against the next view (if we aren't animating its alpha)
|
// Clip against the next view (if we aren't animating its alpha)
|
||||||
nextTv = (TaskView) getChildAt(curIndex + 1);
|
nextTv = (TaskView) getChildAt(curIndex + 1);
|
||||||
if (nextTv.getAlpha() == 1f) {
|
if (nextTv.getAlpha() == 1f) {
|
||||||
Rect curRect = tv.getClippingRect(Utilities.tmpRect, false);
|
Rect curRect = tv.getClippingRect(mTmpRect, false);
|
||||||
Rect nextRect = nextTv.getClippingRect(Utilities.tmpRect2, true);
|
Rect nextRect = nextTv.getClippingRect(mTmpRect2, true);
|
||||||
RecentsConfiguration config = RecentsConfiguration.getInstance();
|
RecentsConfiguration config = RecentsConfiguration.getInstance();
|
||||||
// The hit rects are relative to the task view, which needs to be offset by the
|
// The hit rects are relative to the task view, which needs to be offset by the
|
||||||
// system bar height
|
// system bar height
|
||||||
@@ -528,9 +588,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
mTaskRect.right, mStackRectSansPeek.top + mTaskRect.height());
|
mTaskRect.right, mStackRectSansPeek.top + mTaskRect.height());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mAwaitingFirstLayout) {
|
if (mAwaitingFirstLayout) {
|
||||||
requestSynchronizeStackViewsWithModel();
|
|
||||||
} else {
|
|
||||||
mAwaitingFirstLayout = false;
|
mAwaitingFirstLayout = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -570,13 +628,185 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStackFiltered(TaskStack stack) {
|
public void onStackFiltered(TaskStack newStack, final ArrayList<Task> curStack,
|
||||||
requestSynchronizeStackViewsWithModel();
|
Task filteredTask) {
|
||||||
|
// NOTE: This code assumes that the current (unfiltered) stack is a superset of the new
|
||||||
|
// (filtered) stack
|
||||||
|
// XXX: Use HW Layers
|
||||||
|
|
||||||
|
// Stash the scroll for us to restore to when we unfilter
|
||||||
|
mStashedScroll = getStackScroll();
|
||||||
|
|
||||||
|
// Compute the transforms of the items in the current stack
|
||||||
|
final ArrayList<TaskViewTransform> curTaskTransforms =
|
||||||
|
getStackTransforms(curStack, mStashedScroll, null);
|
||||||
|
|
||||||
|
// Bound the new stack scroll
|
||||||
|
updateMinMaxScroll(false);
|
||||||
|
boundScrollRaw();
|
||||||
|
|
||||||
|
// Compute the transforms of the items in the new stack
|
||||||
|
final ArrayList<TaskViewTransform> taskTransforms =
|
||||||
|
getStackTransforms(mStack.getTasks(), getStackScroll(), null);
|
||||||
|
|
||||||
|
// Animate all of the existing views on screen either out of view (if they are not visible
|
||||||
|
// in the new stack) or to their final positions in the new stack
|
||||||
|
final ArrayList<TaskView> childrenToReturnToPool = new ArrayList<TaskView>();
|
||||||
|
final ArrayList<Task> tasks = mStack.getTasks();
|
||||||
|
ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
|
||||||
|
int childCount = getChildCount();
|
||||||
|
for (int i = 0; i < childCount; i++) {
|
||||||
|
TaskView tv = (TaskView) getChildAt(i);
|
||||||
|
Task task = tv.getTask();
|
||||||
|
TaskViewTransform toTransform;
|
||||||
|
int taskIndex = tasks.indexOf(task);
|
||||||
|
if ((taskIndex < 0) || !taskTransforms.get(taskIndex).visible) {
|
||||||
|
// Compose a new transform that animates the task view out of view
|
||||||
|
TaskViewTransform fromTransform = curTaskTransforms.get(curStack.indexOf(task));
|
||||||
|
toTransform = new TaskViewTransform(fromTransform);
|
||||||
|
tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
|
||||||
|
tv.prepareTaskTransformForFilterTaskHidden(toTransform);
|
||||||
|
|
||||||
|
childrenToReturnToPool.add(tv);
|
||||||
|
} else {
|
||||||
|
toTransform = taskTransforms.get(taskIndex);
|
||||||
|
}
|
||||||
|
childViewAnims.add(tv.getAnimatorToTaskTransform(toTransform));
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatorSet childViewAnimSet = new AnimatorSet();
|
||||||
|
childViewAnimSet.setDuration(
|
||||||
|
Constants.Values.TaskStackView.Animation.FilteredCurrentViewsDuration);
|
||||||
|
childViewAnimSet.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
// Return all the removed children to the view pool
|
||||||
|
for (TaskView tv : childrenToReturnToPool) {
|
||||||
|
mViewPool.returnViewToPool(tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For views that are not already visible, animate them in
|
||||||
|
int taskCount = tasks.size();
|
||||||
|
for (int i = 0; i < taskCount; i++) {
|
||||||
|
Task task = tasks.get(i);
|
||||||
|
TaskViewTransform toTransform = taskTransforms.get(i);
|
||||||
|
if (toTransform.visible) {
|
||||||
|
TaskViewTransform fromTransform =
|
||||||
|
curTaskTransforms.get(curStack.indexOf(task));
|
||||||
|
TaskView tv = getChildViewForTask(task);
|
||||||
|
if (tv == null) {
|
||||||
|
tv = mViewPool.pickUpViewFromPool(task, task);
|
||||||
|
|
||||||
|
// Animate from the current position to the new position
|
||||||
|
tv.prepareTaskTransformForFilterTaskVisible(fromTransform);
|
||||||
|
tv.updateViewPropertiesToTaskTransform(fromTransform,
|
||||||
|
toTransform,
|
||||||
|
Constants.Values.TaskStackView.Animation.FilteredNewViewsDuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
childViewAnimSet.playTogether(childViewAnims);
|
||||||
|
childViewAnimSet.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStackUnfiltered(TaskStack stack) {
|
public void onStackUnfiltered(TaskStack newStack, final ArrayList<Task> curStack) {
|
||||||
requestSynchronizeStackViewsWithModel();
|
// Compute the transforms of the items in the current stack
|
||||||
|
final int curScroll = getStackScroll();
|
||||||
|
final ArrayList<TaskViewTransform> curTaskTransforms =
|
||||||
|
getStackTransforms(curStack, curScroll, null);
|
||||||
|
|
||||||
|
// Restore the stashed scroll
|
||||||
|
updateMinMaxScroll(false);
|
||||||
|
setStackScrollRaw(mStashedScroll);
|
||||||
|
boundScrollRaw();
|
||||||
|
|
||||||
|
// Compute the transforms of the items in the new stack
|
||||||
|
final ArrayList<TaskViewTransform> taskTransforms =
|
||||||
|
getStackTransforms(mStack.getTasks(), getStackScroll(), null);
|
||||||
|
|
||||||
|
// Animate all of the existing views out of view (if they are not in the visible range in
|
||||||
|
// the new stack) or to their final positions in the new stack
|
||||||
|
final ArrayList<TaskView> childrenToRemove = new ArrayList<TaskView>();
|
||||||
|
final ArrayList<Task> tasks = mStack.getTasks();
|
||||||
|
ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
|
||||||
|
int childCount = getChildCount();
|
||||||
|
for (int i = 0; i < childCount; i++) {
|
||||||
|
TaskView tv = (TaskView) getChildAt(i);
|
||||||
|
Task task = tv.getTask();
|
||||||
|
int taskIndex = tasks.indexOf(task);
|
||||||
|
TaskViewTransform transform;
|
||||||
|
|
||||||
|
// If the view is no longer visible, then we should just animate it out
|
||||||
|
if (taskIndex < 0 || !taskTransforms.get(taskIndex).visible) {
|
||||||
|
transform = new TaskViewTransform(curTaskTransforms.get(curStack.indexOf(task)));
|
||||||
|
tv.prepareTaskTransformForFilterTaskVisible(transform);
|
||||||
|
childrenToRemove.add(tv);
|
||||||
|
} else {
|
||||||
|
transform = taskTransforms.get(taskIndex);
|
||||||
|
}
|
||||||
|
childViewAnims.add(tv.getAnimatorToTaskTransform(transform));
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatorSet childViewAnimSet = new AnimatorSet();
|
||||||
|
childViewAnimSet.setDuration(
|
||||||
|
Constants.Values.TaskStackView.Animation.UnfilteredCurrentViewsDuration);
|
||||||
|
childViewAnimSet.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
// Return all the removed children to the view pool
|
||||||
|
for (TaskView tv : childrenToRemove) {
|
||||||
|
mViewPool.returnViewToPool(tv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the hw layers ref count
|
||||||
|
addHwLayersRefCount("unfilteredNewViews");
|
||||||
|
|
||||||
|
// For views that are not already visible, animate them in
|
||||||
|
ArrayList<Animator> newViewAnims = new ArrayList<Animator>();
|
||||||
|
AnimatorSet newViewAnimSet = new AnimatorSet();
|
||||||
|
int taskCount = tasks.size();
|
||||||
|
int offset = 0;
|
||||||
|
for (int i = 0; i < taskCount; i++) {
|
||||||
|
Task task = tasks.get(i);
|
||||||
|
TaskViewTransform toTransform = taskTransforms.get(i);
|
||||||
|
if (toTransform.visible) {
|
||||||
|
TaskView tv = getChildViewForTask(task);
|
||||||
|
if (tv == null) {
|
||||||
|
// For views that are not already visible, animate them in
|
||||||
|
tv = mViewPool.pickUpViewFromPool(task, task);
|
||||||
|
|
||||||
|
// Animate in this new view
|
||||||
|
TaskViewTransform fromTransform = new TaskViewTransform(toTransform);
|
||||||
|
tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
|
||||||
|
tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
|
||||||
|
newViewAnims.add(tv.getAnimatorToTaskTransform(toTransform));
|
||||||
|
offset++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the animation
|
||||||
|
newViewAnimSet.setDuration(
|
||||||
|
Constants.Values.TaskStackView.Animation.UnfilteredNewViewsDuration);
|
||||||
|
newViewAnimSet.playTogether(newViewAnims);
|
||||||
|
newViewAnimSet.addListener(new AnimatorListenerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void onAnimationEnd(Animator animation) {
|
||||||
|
// Decrement the hw layers ref count
|
||||||
|
decHwLayersRefCount("unfilteredNewViews");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
newViewAnimSet.start();
|
||||||
|
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
childViewAnimSet.playTogether(childViewAnims);
|
||||||
|
childViewAnimSet.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**** ViewPoolConsumer Implementation ****/
|
/**** ViewPoolConsumer Implementation ****/
|
||||||
@@ -845,7 +1075,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
|||||||
|
|
||||||
/** Handles touch events once we have intercepted them */
|
/** Handles touch events once we have intercepted them */
|
||||||
public boolean onTouchEvent(MotionEvent ev) {
|
public boolean onTouchEvent(MotionEvent ev) {
|
||||||
Console.log(Constants.DebugFlags.TaskStack.SynchronizeViewsWithModel,
|
Console.log(Constants.DebugFlags.UI.TouchEvents,
|
||||||
"[TaskStackViewTouchHandler|touchEvent]",
|
"[TaskStackViewTouchHandler|touchEvent]",
|
||||||
Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
|
Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
|
||||||
|
|
||||||
@@ -1045,9 +1275,17 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
|||||||
ActivityManager.REMOVE_TASK_KILL_PROCESS);
|
ActivityManager.REMOVE_TASK_KILL_PROCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are no remaining tasks, then just close the activity
|
// If there are no remaining tasks, then either unfilter the current stack, or just close
|
||||||
|
// the activity if there are no filtered stacks
|
||||||
if (mSv.mStack.getTaskCount() == 0) {
|
if (mSv.mStack.getTaskCount() == 0) {
|
||||||
activity.finish();
|
boolean shouldFinishActivity = true;
|
||||||
|
if (mSv.mStack.hasFilteredTasks()) {
|
||||||
|
mSv.mStack.unfilterTasks();
|
||||||
|
shouldFinishActivity = (mSv.mStack.getTaskCount() == 0);
|
||||||
|
}
|
||||||
|
if (shouldFinishActivity) {
|
||||||
|
activity.finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable HW layers
|
// Disable HW layers
|
||||||
|
|||||||
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package com.android.systemui.recents.views;
|
package com.android.systemui.recents.views;
|
||||||
|
|
||||||
|
import android.animation.Animator;
|
||||||
|
import android.animation.AnimatorSet;
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
@@ -72,6 +75,7 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
|
|||||||
// Bind the views
|
// Bind the views
|
||||||
mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
|
mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
|
||||||
mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
|
mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
|
||||||
|
mBarView.mActivityIcon.setOnClickListener(this);
|
||||||
if (mTaskDataLoaded) {
|
if (mTaskDataLoaded) {
|
||||||
onTaskDataLoaded(false);
|
onTaskDataLoaded(false);
|
||||||
}
|
}
|
||||||
@@ -90,12 +94,16 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas) {
|
protected void dispatchDraw(Canvas canvas) {
|
||||||
|
int restoreCount = 0;
|
||||||
if (Constants.Values.TaskView.UseRoundedCorners) {
|
if (Constants.Values.TaskView.UseRoundedCorners) {
|
||||||
|
restoreCount = canvas.save();
|
||||||
canvas.clipPath(mRoundedRectClipPath);
|
canvas.clipPath(mRoundedRectClipPath);
|
||||||
}
|
}
|
||||||
|
super.dispatchDraw(canvas);
|
||||||
super.onDraw(canvas);
|
if (Constants.Values.TaskView.UseRoundedCorners) {
|
||||||
|
canvas.restoreToCount(restoreCount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set callback */
|
/** Set callback */
|
||||||
@@ -109,27 +117,43 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Synchronizes this view's properties with the task's transform */
|
/** Synchronizes this view's properties with the task's transform */
|
||||||
void updateViewPropertiesFromTask(TaskViewTransform animateFromTransform,
|
void updateViewPropertiesToTaskTransform(TaskViewTransform animateFromTransform,
|
||||||
TaskViewTransform transform, int duration) {
|
TaskViewTransform toTransform, int duration) {
|
||||||
if (duration > 0) {
|
if (duration > 0) {
|
||||||
if (animateFromTransform != null) {
|
if (animateFromTransform != null) {
|
||||||
setTranslationY(animateFromTransform.translationY);
|
setTranslationY(animateFromTransform.translationY);
|
||||||
setScaleX(animateFromTransform.scale);
|
setScaleX(animateFromTransform.scale);
|
||||||
setScaleY(animateFromTransform.scale);
|
setScaleY(animateFromTransform.scale);
|
||||||
|
setAlpha(animateFromTransform.alpha);
|
||||||
}
|
}
|
||||||
animate().translationY(transform.translationY)
|
animate().translationY(toTransform.translationY)
|
||||||
.scaleX(transform.scale)
|
.scaleX(toTransform.scale)
|
||||||
.scaleY(transform.scale)
|
.scaleY(toTransform.scale)
|
||||||
|
.alpha(toTransform.alpha)
|
||||||
.setDuration(duration)
|
.setDuration(duration)
|
||||||
.setInterpolator(new AccelerateDecelerateInterpolator())
|
.setInterpolator(new AccelerateDecelerateInterpolator())
|
||||||
|
.withLayer()
|
||||||
.start();
|
.start();
|
||||||
} else {
|
} else {
|
||||||
setTranslationY(transform.translationY);
|
setTranslationY(toTransform.translationY);
|
||||||
setScaleX(transform.scale);
|
setScaleX(toTransform.scale);
|
||||||
setScaleY(transform.scale);
|
setScaleY(toTransform.scale);
|
||||||
|
setAlpha(toTransform.alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Returns an animator to animate this task to the specified transform */
|
||||||
|
Animator getAnimatorToTaskTransform(TaskViewTransform toTransform) {
|
||||||
|
AnimatorSet anims = new AnimatorSet();
|
||||||
|
anims.playTogether(
|
||||||
|
ObjectAnimator.ofFloat(this, "translationY", toTransform.translationY),
|
||||||
|
ObjectAnimator.ofFloat(this, "scaleX", toTransform.scale),
|
||||||
|
ObjectAnimator.ofFloat(this, "scaleY", toTransform.scale),
|
||||||
|
ObjectAnimator.ofFloat(this, "alpha", toTransform.alpha)
|
||||||
|
);
|
||||||
|
return anims;
|
||||||
|
}
|
||||||
|
|
||||||
/** Resets this view's properties */
|
/** Resets this view's properties */
|
||||||
void resetViewProperties() {
|
void resetViewProperties() {
|
||||||
setTranslationX(0f);
|
setTranslationX(0f);
|
||||||
@@ -139,6 +163,17 @@ public class TaskView extends FrameLayout implements View.OnClickListener, Task.
|
|||||||
setAlpha(1f);
|
setAlpha(1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void prepareTaskTransformForFilterTaskHidden(TaskViewTransform toTransform) {
|
||||||
|
// Fade the view out and slide it away
|
||||||
|
toTransform.alpha = 0f;
|
||||||
|
toTransform.translationY += 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepareTaskTransformForFilterTaskVisible(TaskViewTransform fromTransform) {
|
||||||
|
// Fade the view in
|
||||||
|
fromTransform.alpha = 0f;
|
||||||
|
}
|
||||||
|
|
||||||
/** Animates this task view as it enters recents */
|
/** Animates this task view as it enters recents */
|
||||||
public void animateOnEnterRecents() {
|
public void animateOnEnterRecents() {
|
||||||
RecentsConfiguration config = RecentsConfiguration.getInstance();
|
RecentsConfiguration config = RecentsConfiguration.getInstance();
|
||||||
|
|||||||
@@ -23,13 +23,27 @@ import android.graphics.Rect;
|
|||||||
public class TaskViewTransform {
|
public class TaskViewTransform {
|
||||||
public int translationY = 0;
|
public int translationY = 0;
|
||||||
public float scale = 1f;
|
public float scale = 1f;
|
||||||
public boolean visible = true;
|
public float alpha = 1f;
|
||||||
|
public boolean visible = false;
|
||||||
public Rect rect = new Rect();
|
public Rect rect = new Rect();
|
||||||
float t;
|
float t;
|
||||||
|
|
||||||
|
public TaskViewTransform() {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskViewTransform(TaskViewTransform o) {
|
||||||
|
translationY = o.translationY;
|
||||||
|
scale = o.scale;
|
||||||
|
alpha = o.alpha;
|
||||||
|
visible = o.visible;
|
||||||
|
rect.set(o.rect);
|
||||||
|
t = o.t;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "TaskViewTransform y: " + translationY + " scale: " + scale +
|
return "TaskViewTransform y: " + translationY + " scale: " + scale + " alpha: " + alpha +
|
||||||
" visible: " + visible + " rect: " + rect;
|
" visible: " + visible + " rect: " + rect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user