summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java116
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java10
3 files changed, 79 insertions, 70 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 88bebdbf173b..e67b75f263dc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -16,20 +16,16 @@
package com.android.systemui.recents.views;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.ArrayMap;
import android.util.ArraySet;
-import android.util.FloatProperty;
-import android.util.Property;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.view.ViewDebug;
-import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivityLaunchState;
@@ -135,11 +131,11 @@ public class TaskStackLayoutAlgorithm {
new FreePathInterpolator(FOCUSED_DIM_PATH);
// The various focus states
- public static final float STATE_FOCUSED = 1f;
- public static final float STATE_UNFOCUSED = 0f;
+ public static final int STATE_FOCUSED = 1;
+ public static final int STATE_UNFOCUSED = 0;
public interface TaskStackLayoutAlgorithmCallbacks {
- void onFocusStateChanged(float prevFocusState, float curFocusState);
+ void onFocusStateChanged(int prevFocusState, int curFocusState);
}
/**
@@ -209,24 +205,6 @@ public class TaskStackLayoutAlgorithm {
}
}
- /**
- * A Property wrapper around the <code>focusState</code> functionality handled by the
- * {@link TaskStackLayoutAlgorithm#setFocusState(float)} and
- * {@link TaskStackLayoutAlgorithm#getFocusState()} methods.
- */
- private static final Property<TaskStackLayoutAlgorithm, Float> FOCUS_STATE =
- new FloatProperty<TaskStackLayoutAlgorithm>("focusState") {
- @Override
- public void setValue(TaskStackLayoutAlgorithm object, float value) {
- object.setFocusState(value);
- }
-
- @Override
- public Float get(TaskStackLayoutAlgorithm object) {
- return object.getFocusState();
- }
- };
-
// A report of the visibility state of the stack
public class VisibilityReport {
public int numVisibleTasks;
@@ -289,10 +267,7 @@ public class TaskStackLayoutAlgorithm {
// The state of the stack focus (0..1), which controls the transition of the stack from the
// focused to non-focused state
@ViewDebug.ExportedProperty(category="recents")
- private float mFocusState;
-
- // The animator used to reset the focused state
- private ObjectAnimator mFocusStateAnimator;
+ private int mFocusState;
// The smallest scroll progress, at this value, the back most task will be visible
@ViewDebug.ExportedProperty(category="recents")
@@ -321,7 +296,8 @@ public class TaskStackLayoutAlgorithm {
int mMaxTranslationZ;
// Optimization, allows for quick lookup of task -> index
- private ArrayMap<Task.TaskKey, Integer> mTaskIndexMap = new ArrayMap<>();
+ private SparseIntArray mTaskIndexMap = new SparseIntArray();
+ private SparseArray<Float> mTaskIndexOverrideMap = new SparseArray<>();
// The freeform workspace layout
FreeformWorkspaceLayoutAlgorithm mFreeformLayoutAlgorithm;
@@ -354,6 +330,7 @@ public class TaskStackLayoutAlgorithm {
* Resets this layout when the stack view is reset.
*/
public void reset() {
+ mTaskIndexOverrideMap.clear();
setFocusState(getDefaultFocusState());
}
@@ -367,8 +344,8 @@ public class TaskStackLayoutAlgorithm {
/**
* Sets the focused state.
*/
- public void setFocusState(float focusState) {
- float prevFocusState = mFocusState;
+ public void setFocusState(int focusState) {
+ int prevFocusState = mFocusState;
mFocusState = focusState;
updateFrontBackTransforms();
if (mCb != null) {
@@ -379,7 +356,7 @@ public class TaskStackLayoutAlgorithm {
/**
* Gets the focused state.
*/
- public float getFocusState() {
+ public int getFocusState() {
return mFocusState;
}
@@ -469,7 +446,7 @@ public class TaskStackLayoutAlgorithm {
int taskCount = stackTasks.size();
for (int i = 0; i < taskCount; i++) {
Task task = stackTasks.get(i);
- mTaskIndexMap.put(task.key, i);
+ mTaskIndexMap.put(task.key.id, i);
}
// Calculate the min/max scroll
@@ -516,35 +493,56 @@ public class TaskStackLayoutAlgorithm {
}
/**
- * Updates this stack when a scroll happens.
+ * Adds and override task progress for the given task when transitioning from focused to
+ * unfocused state.
*/
- public void updateFocusStateOnScroll(int yMovement) {
- Utilities.cancelAnimationWithoutCallbacks(mFocusStateAnimator);
- if (mFocusState > STATE_UNFOCUSED) {
- float delta = (float) yMovement / (UNFOCUS_MULTIPLIER * mStackRect.height());
- setFocusState(mFocusState - Math.min(mFocusState, Math.abs(delta)));
+ public void addUnfocusedTaskOverride(Task task, float stackScroll) {
+ if (mFocusState != STATE_UNFOCUSED) {
+ mFocusedRange.offset(stackScroll);
+ mUnfocusedRange.offset(stackScroll);
+ float focusedRangeX = mFocusedRange.getNormalizedX(mTaskIndexMap.get(task.key.id));
+ float focusedY = mFocusedCurveInterpolator.getInterpolation(focusedRangeX);
+ float unfocusedRangeX = mUnfocusedCurveInterpolator.getX(focusedY);
+ float unfocusedTaskProgress = stackScroll + mUnfocusedRange.getAbsoluteX(unfocusedRangeX);
+ if (Float.compare(focusedRangeX, unfocusedRangeX) != 0) {
+ mTaskIndexOverrideMap.put(task.key.id, unfocusedTaskProgress);
+ }
}
}
/**
- * Aniamtes the focused state back to its orginal state.
+ * Updates this stack when a scroll happens.
*/
- public void animateFocusState(float newState) {
- Utilities.cancelAnimationWithoutCallbacks(mFocusStateAnimator);
- if (Float.compare(newState, getFocusState()) != 0) {
- mFocusStateAnimator = ObjectAnimator.ofFloat(this, FOCUS_STATE, getFocusState(),
- newState);
- mFocusStateAnimator.setDuration(mContext.getResources().getInteger(
- R.integer.recents_animate_task_stack_scroll_duration));
- mFocusStateAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
- mFocusStateAnimator.start();
+ public void updateFocusStateOnScroll(float stackScroll, float deltaScroll) {
+ for (int i = mTaskIndexOverrideMap.size() - 1; i >= 0; i--) {
+ int taskId = mTaskIndexOverrideMap.keyAt(i);
+ float x = mTaskIndexMap.get(taskId);
+ float overrideX = mTaskIndexOverrideMap.get(taskId, 0f);
+ float newOverrideX = overrideX + deltaScroll;
+ mUnfocusedRange.offset(stackScroll);
+ boolean outOfBounds = mUnfocusedRange.getNormalizedX(newOverrideX) < 0f ||
+ mUnfocusedRange.getNormalizedX(newOverrideX) > 1f;
+ if (outOfBounds || (overrideX >= x && x >= newOverrideX) ||
+ (overrideX <= x && x <= newOverrideX)) {
+ // Remove the override once we reach the original task index
+ mTaskIndexOverrideMap.removeAt(i);
+ } else if ((overrideX >= x && deltaScroll <= 0f) ||
+ (overrideX <= x && deltaScroll >= 0f)) {
+ // Scrolling from override x towards x, then lock the task in place
+ mTaskIndexOverrideMap.put(taskId, newOverrideX);
+ } else {
+ // Scrolling override x away from x, we should still move the scroll towards x
+ float deltaX = overrideX - x;
+ newOverrideX = Math.signum(deltaX) * (Math.abs(deltaX) - deltaScroll);
+ mTaskIndexOverrideMap.put(taskId, x + newOverrideX);
+ }
}
}
/**
* Returns the default focus state.
*/
- public float getDefaultFocusState() {
+ public int getDefaultFocusState() {
return STATE_FOCUSED;
}
@@ -650,18 +648,19 @@ public class TaskStackLayoutAlgorithm {
false /* forceUpdate */);
}
- public TaskViewTransform getStackTransform(Task task, float stackScroll, float focusState,
+ public TaskViewTransform getStackTransform(Task task, float stackScroll, int focusState,
TaskViewTransform transformOut, TaskViewTransform frontTransform, boolean forceUpdate) {
if (mFreeformLayoutAlgorithm.isTransformAvailable(task, this)) {
mFreeformLayoutAlgorithm.getTransform(task, transformOut, this);
return transformOut;
} else {
// Return early if we have an invalid index
- if (task == null || !mTaskIndexMap.containsKey(task.key)) {
+ if (task == null || mTaskIndexMap.get(task.key.id, -1) == -1) {
transformOut.reset();
return transformOut;
}
- getStackTransform(mTaskIndexMap.get(task.key), stackScroll, focusState, transformOut,
+ float taskProgress = getStackScrollForTask(task);
+ getStackTransform(taskProgress, stackScroll, focusState, transformOut,
frontTransform, false /* ignoreSingleTaskCase */, forceUpdate);
return transformOut;
}
@@ -687,7 +686,7 @@ public class TaskStackLayoutAlgorithm {
* internally to ensure that we can calculate the transform for any
* position in the stack.
*/
- public void getStackTransform(float taskProgress, float stackScroll, float focusState,
+ public void getStackTransform(float taskProgress, float stackScroll, int focusState,
TaskViewTransform transformOut, TaskViewTransform frontTransform,
boolean ignoreSingleTaskCase, boolean forceUpdate) {
SystemServicesProxy ssp = Recents.getSystemServices();
@@ -773,8 +772,7 @@ public class TaskStackLayoutAlgorithm {
* stack.
*/
float getStackScrollForTask(Task t) {
- if (!mTaskIndexMap.containsKey(t.key)) return 0f;
- return mTaskIndexMap.get(t.key);
+ return mTaskIndexOverrideMap.get(t.key.id, (float) mTaskIndexMap.get(t.key.id, 0));
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 1707c4f4ccd0..d5f88f7ac56c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -665,7 +665,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
public void getCurrentTaskTransforms(ArrayList<Task> tasks,
ArrayList<TaskViewTransform> transformsOut) {
Utilities.matchTaskListSize(tasks, transformsOut);
- float focusState = mLayoutAlgorithm.getFocusState();
+ int focusState = mLayoutAlgorithm.getFocusState();
for (int i = tasks.size() - 1; i >= 0; i--) {
Task task = tasks.get(i);
TaskViewTransform transform = transformsOut.get(i);
@@ -684,7 +684,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
* Returns the task transforms for all the tasks in the stack if the stack was at the given
* {@param stackScroll} and {@param focusState}.
*/
- public void getLayoutTaskTransforms(float stackScroll, float focusState, ArrayList<Task> tasks,
+ public void getLayoutTaskTransforms(float stackScroll, int focusState, ArrayList<Task> tasks,
ArrayList<TaskViewTransform> transformsOut) {
Utilities.matchTaskListSize(tasks, transformsOut);
for (int i = tasks.size() - 1; i >= 0; i--) {
@@ -1055,7 +1055,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
protected Parcelable onSaveInstanceState() {
Bundle savedState = new Bundle();
savedState.putParcelable(KEY_SAVED_STATE_SUPER, super.onSaveInstanceState());
- savedState.putFloat(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE, mLayoutAlgorithm.getFocusState());
+ savedState.putInt(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE, mLayoutAlgorithm.getFocusState());
savedState.putFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL, mStackScroller.getStackScroll());
return super.onSaveInstanceState();
}
@@ -1065,7 +1065,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
Bundle savedState = (Bundle) state;
super.onRestoreInstanceState(savedState.getParcelable(KEY_SAVED_STATE_SUPER));
- mLayoutAlgorithm.setFocusState(savedState.getFloat(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE));
+ mLayoutAlgorithm.setFocusState(savedState.getInt(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE));
mStackScroller.setStackScroll(savedState.getFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL));
}
@@ -1517,7 +1517,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/**** TaskStackLayoutAlgorithm.TaskStackLayoutAlgorithmCallbacks ****/
@Override
- public void onFocusStateChanged(float prevFocusState, float curFocusState) {
+ public void onFocusStateChanged(int prevFocusState, int curFocusState) {
if (mDeferredTaskViewLayoutAnimation == null) {
mUIDozeTrigger.poke();
relayoutTaskViewsOnNextFrame(AnimationProps.IMMEDIATE);
@@ -1532,6 +1532,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
if (animation != null) {
relayoutTaskViewsOnNextFrame(animation);
}
+ mLayoutAlgorithm.updateFocusStateOnScroll(curScroll, curScroll - prevScroll);
if (mEnterAnimationComplete) {
if (shouldShowHistoryButton() &&
@@ -1636,11 +1637,19 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
public final void onBusEvent(FocusNextTaskViewEvent event) {
+ // Stop any scrolling
+ mStackScroller.stopScroller();
+ mStackScroller.stopBoundScrollAnimation();
+
setRelativeFocusedTask(true, false /* stackTasksOnly */, true /* animated */, false,
event.timerIndicatorDuration);
}
public final void onBusEvent(FocusPreviousTaskViewEvent event) {
+ // Stop any scrolling
+ mStackScroller.stopScroller();
+ mStackScroller.stopBoundScrollAnimation();
+
setRelativeFocusedTask(false, false /* stackTasksOnly */, true /* animated */);
}
@@ -1771,10 +1780,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
removeIgnoreTask(event.task);
}
- public final void onBusEvent(StackViewScrolledEvent event) {
- mLayoutAlgorithm.updateFocusStateOnScroll(event.yMovement.value);
- }
-
public final void onBusEvent(IterateRecentsEvent event) {
if (!mEnterAnimationComplete) {
// Cancel the previous task's window transition before animating the focused state
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 3f0630d70c94..20933ee3cf6f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -223,6 +223,13 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
int xDiff = Math.abs(x - mDownX);
if (Math.abs(y - mDownY) > mScrollTouchSlop && yDiff > xDiff) {
mIsScrolling = true;
+ float stackScroll = mScroller.getStackScroll();
+ List<TaskView> taskViews = mSv.getTaskViews();
+ for (int i = taskViews.size() - 1; i >= 0; i--) {
+ layoutAlgorithm.addUnfocusedTaskOverride(taskViews.get(i).getTask(),
+ stackScroll);
+ }
+ layoutAlgorithm.setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
// Disallow parents from intercepting touch events
final ViewParent parent = mSv.getParent();
@@ -429,8 +436,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
// Otherwise, offset the scroll by the movement of the anchor task
float anchorTaskScroll = layoutAlgorithm.getStackScrollForTask(anchorTask);
float stackScrollOffset = (anchorTaskScroll - prevAnchorTaskScroll);
- if (layoutAlgorithm.getFocusState() !=
- TaskStackLayoutAlgorithm.STATE_FOCUSED) {
+ if (layoutAlgorithm.getFocusState() != TaskStackLayoutAlgorithm.STATE_FOCUSED) {
// If we are focused, we don't want the front task to move, but otherwise, we
// allow the back task to move up, and the front task to move back
stackScrollOffset /= 2;