Merge changes If7b8ed3f,I309c3825,Iafd06419,I59f73caf into nyc-dev
* changes: Fixes several animation issues related to a dismissing task. Pipe the dismiss button logic through the touch handler. Skip scroll-to animation when undocking and there are no tasks. Fixing issue with docking being disallowed for secondary user.
This commit is contained in:
@@ -86,7 +86,7 @@ public class DividerSnapAlgorithm {
|
||||
return new DividerSnapAlgorithm(ctx.getResources(),
|
||||
displayInfo.logicalWidth, displayInfo.logicalHeight,
|
||||
dividerWindowWidth - 2 * dividerInsets,
|
||||
ctx.getResources().getConfiguration().orientation
|
||||
ctx.getApplicationContext().getResources().getConfiguration().orientation
|
||||
== Configuration.ORIENTATION_PORTRAIT,
|
||||
insets);
|
||||
}
|
||||
|
||||
@@ -451,11 +451,13 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
|
||||
|
||||
TaskStack stack = loadPlan.getTaskStack();
|
||||
int numStackTasks = stack.getStackTaskCount();
|
||||
boolean showDeferredAnimation = numStackTasks > 0;
|
||||
|
||||
EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
|
||||
false /* fromDeviceOrientationChange */, false /* fromDisplayDensityChange */,
|
||||
numStackTasks > 0));
|
||||
EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode, stack));
|
||||
EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode,
|
||||
showDeferredAnimation, stack));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,10 +25,14 @@ import com.android.systemui.recents.model.TaskStack;
|
||||
public class MultiWindowStateChangedEvent extends EventBus.AnimatedEvent {
|
||||
|
||||
public final boolean inMultiWindow;
|
||||
// This flag is only used when undocking a task
|
||||
public final boolean showDeferredAnimation;
|
||||
public final TaskStack stack;
|
||||
|
||||
public MultiWindowStateChangedEvent(boolean inMultiWindow, TaskStack stack) {
|
||||
public MultiWindowStateChangedEvent(boolean inMultiWindow, boolean showDeferredAnimation,
|
||||
TaskStack stack) {
|
||||
this.inMultiWindow = inMultiWindow;
|
||||
this.showDeferredAnimation = showDeferredAnimation;
|
||||
this.stack = stack;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.systemui.recents.events.ui;
|
||||
|
||||
import com.android.systemui.recents.events.EventBus;
|
||||
import com.android.systemui.recents.model.Task;
|
||||
import com.android.systemui.recents.views.AnimationProps;
|
||||
import com.android.systemui.recents.views.TaskView;
|
||||
|
||||
/**
|
||||
@@ -27,9 +28,11 @@ public class TaskViewDismissedEvent extends EventBus.Event {
|
||||
|
||||
public final Task task;
|
||||
public final TaskView taskView;
|
||||
public final AnimationProps animation;
|
||||
|
||||
public TaskViewDismissedEvent(Task task, TaskView taskView) {
|
||||
public TaskViewDismissedEvent(Task task, TaskView taskView, AnimationProps animation) {
|
||||
this.task = task;
|
||||
this.taskView = taskView;
|
||||
this.animation = animation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ public class RecentsViewTouchHandler {
|
||||
}
|
||||
|
||||
public final void onBusEvent(ConfigurationChangedEvent event) {
|
||||
if (event.fromDisplayDensityChange) {
|
||||
if (event.fromDisplayDensityChange || event.fromDeviceOrientationChange) {
|
||||
updateSnapAlgorithm();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.systemui.recents.views;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
@@ -309,6 +310,11 @@ public class TaskStackAnimationHelper {
|
||||
for (int i = 0; i < taskViewCount; i++) {
|
||||
int taskIndexFromFront = taskViewCount - i - 1;
|
||||
TaskView tv = taskViews.get(i);
|
||||
Task task = tv.getTask();
|
||||
|
||||
if (mStackView.isIgnoredTask(task)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Animate the tasks down
|
||||
AnimationProps taskAnimation;
|
||||
@@ -384,29 +390,29 @@ public class TaskStackAnimationHelper {
|
||||
*/
|
||||
public void startDeleteTaskAnimation(final TaskView deleteTaskView,
|
||||
final ReferenceCountedTrigger postAnimationTrigger) {
|
||||
Resources res = mStackView.getResources();
|
||||
TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
|
||||
TaskStackViewTouchHandler touchHandler = mStackView.getTouchHandler();
|
||||
touchHandler.onBeginManualDrag(deleteTaskView);
|
||||
|
||||
int offscreenXOffset = mStackView.getMeasuredWidth() - stackLayout.mTaskRect.left;
|
||||
postAnimationTrigger.increment();
|
||||
postAnimationTrigger.addLastDecrementRunnable(() -> {
|
||||
touchHandler.onChildDismissed(deleteTaskView);
|
||||
});
|
||||
|
||||
// Disabling clipping with the stack while the view is animating away, this will get
|
||||
// restored when the task is next picked up from the view pool
|
||||
deleteTaskView.setClipViewInStack(false);
|
||||
|
||||
// Compose the new animation and transform and star the animation
|
||||
AnimationProps taskAnimation = new AnimationProps(DISMISS_TASK_DURATION,
|
||||
Interpolators.ALPHA_OUT, new AnimatorListenerAdapter() {
|
||||
final float dismissSize = touchHandler.getScaledDismissSize();
|
||||
ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
|
||||
animator.setDuration(400);
|
||||
animator.addUpdateListener((animation) -> {
|
||||
float progress = (Float) animation.getAnimatedValue();
|
||||
deleteTaskView.setTranslationX(progress * dismissSize);
|
||||
touchHandler.updateSwipeProgress(deleteTaskView, true, progress);
|
||||
});
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
postAnimationTrigger.decrement();
|
||||
}
|
||||
});
|
||||
postAnimationTrigger.increment();
|
||||
|
||||
mTmpTransform.fillIn(deleteTaskView);
|
||||
mTmpTransform.alpha = 0f;
|
||||
mTmpTransform.rect.offset(offscreenXOffset, 0);
|
||||
mStackView.updateTaskViewToTransform(deleteTaskView, mTmpTransform, taskAnimation);
|
||||
animator.start();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -419,7 +425,6 @@ public class TaskStackAnimationHelper {
|
||||
int offscreenXOffset = mStackView.getMeasuredWidth() - stackLayout.mTaskRect.left;
|
||||
|
||||
int taskViewCount = taskViews.size();
|
||||
|
||||
for (int i = taskViewCount - 1; i >= 0; i--) {
|
||||
TaskView tv = taskViews.get(i);
|
||||
int taskIndexFromFront = taskViewCount - i - 1;
|
||||
|
||||
@@ -623,6 +623,24 @@ public class TaskStackLayoutAlgorithm {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds and override task progress for the given task when transitioning from focused to
|
||||
* unfocused state.
|
||||
*/
|
||||
public void addUnfocusedTaskOverride(TaskView taskView, float stackScroll) {
|
||||
mFocusedRange.offset(stackScroll);
|
||||
mUnfocusedRange.offset(stackScroll);
|
||||
|
||||
Task task = taskView.getTask();
|
||||
int top = taskView.getTop() - mTaskRect.top;
|
||||
float focusedRangeX = getNormalizedXFromFocusedY(top, FROM_TOP);
|
||||
float unfocusedRangeX = getNormalizedXFromUnfocusedY(top, FROM_TOP);
|
||||
float unfocusedTaskProgress = stackScroll + mUnfocusedRange.getAbsoluteX(unfocusedRangeX);
|
||||
if (Float.compare(focusedRangeX, unfocusedRangeX) != 0) {
|
||||
mTaskIndexOverrideMap.put(task.key.id, unfocusedTaskProgress);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearUnfocusedTaskOverrides() {
|
||||
mTaskIndexOverrideMap.clear();
|
||||
}
|
||||
|
||||
@@ -419,6 +419,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
return mLayoutAlgorithm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the touch handler for this task stack.
|
||||
*/
|
||||
public TaskStackViewTouchHandler getTouchHandler() {
|
||||
return mTouchHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a task to the ignored set.
|
||||
*/
|
||||
@@ -1664,7 +1671,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
|
||||
public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
|
||||
// Stop any scrolling
|
||||
mTouchHandler.finishAnimations();
|
||||
mTouchHandler.cancelNonDismissTaskAnimations();
|
||||
mStackScroller.stopScroller();
|
||||
mStackScroller.stopBoundScrollAnimation();
|
||||
cancelDeferredTaskViewLayoutAnimation();
|
||||
@@ -1722,8 +1729,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
R.string.accessibility_recents_item_dismissed, event.task.title));
|
||||
|
||||
// Remove the task from the stack
|
||||
mStack.removeTask(event.task, new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
|
||||
Interpolators.FAST_OUT_SLOW_IN), false /* fromDockGesture */);
|
||||
mStack.removeTask(event.task, event.animation, false /* fromDockGesture */);
|
||||
EventBus.getDefault().send(new DeleteTaskDataEvent(event.task));
|
||||
|
||||
MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_DISMISS,
|
||||
@@ -1938,7 +1944,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
|
||||
}
|
||||
|
||||
public final void onBusEvent(final MultiWindowStateChangedEvent event) {
|
||||
if (event.inMultiWindow) {
|
||||
if (event.inMultiWindow || !event.showDeferredAnimation) {
|
||||
setTasks(event.stack, true /* allowNotifyStackChanges */);
|
||||
} else {
|
||||
// Reset the launch state before handling the multiwindow change
|
||||
|
||||
@@ -32,7 +32,6 @@ import android.view.ViewConfiguration;
|
||||
import android.view.ViewDebug;
|
||||
import android.view.ViewParent;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
||||
@@ -189,15 +188,30 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes all scroll-fling and swipe animations currently running.
|
||||
* Finishes all scroll-fling and non-dismissing animations currently running.
|
||||
*/
|
||||
public void finishAnimations() {
|
||||
public void cancelNonDismissTaskAnimations() {
|
||||
Utilities.cancelAnimationWithoutCallbacks(mScrollFlingAnimator);
|
||||
ArrayMap<View, Animator> existingAnimators = new ArrayMap<>(mSwipeHelperAnimations);
|
||||
for (int i = 0; i < existingAnimators.size(); i++) {
|
||||
existingAnimators.get(existingAnimators.keyAt(i)).end();
|
||||
if (!mSwipeHelperAnimations.isEmpty()) {
|
||||
// For the non-dismissing tasks, freeze the position into the task overrides
|
||||
List<TaskView> taskViews = mSv.getTaskViews();
|
||||
for (int i = taskViews.size() - 1; i >= 0; i--) {
|
||||
TaskView tv = taskViews.get(i);
|
||||
|
||||
if (mSv.isIgnoredTask(tv.getTask())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tv.cancelTransformAnimation();
|
||||
mSv.getStackAlgorithm().addUnfocusedTaskOverride(tv, mTargetStackScroll);
|
||||
}
|
||||
mSv.getStackAlgorithm().setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
|
||||
// Update the scroll to the final scroll position from onBeginDrag()
|
||||
mSv.getScroller().setStackScroll(mTargetStackScroll, null);
|
||||
|
||||
mSwipeHelperAnimations.clear();
|
||||
}
|
||||
mSwipeHelperAnimations.clear();
|
||||
mActiveTaskView = null;
|
||||
}
|
||||
|
||||
private boolean handleTouchEvent(MotionEvent ev) {
|
||||
@@ -210,6 +224,13 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
||||
int action = ev.getAction();
|
||||
switch (action & MotionEvent.ACTION_MASK) {
|
||||
case MotionEvent.ACTION_DOWN: {
|
||||
// Stop the current scroll if it is still flinging
|
||||
mScroller.stopScroller();
|
||||
mScroller.stopBoundScrollAnimation();
|
||||
mScroller.resetDeltaScroll();
|
||||
cancelNonDismissTaskAnimations();
|
||||
mSv.cancelDeferredTaskViewLayoutAnimation();
|
||||
|
||||
// Save the touch down info
|
||||
mDownX = (int) ev.getX();
|
||||
mDownY = (int) ev.getY();
|
||||
@@ -218,13 +239,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
||||
mActivePointerId = ev.getPointerId(0);
|
||||
mActiveTaskView = findViewAtPoint(mDownX, mDownY);
|
||||
|
||||
// Stop the current scroll if it is still flinging
|
||||
mSv.cancelDeferredTaskViewLayoutAnimation();
|
||||
mScroller.stopScroller();
|
||||
mScroller.stopBoundScrollAnimation();
|
||||
mScroller.resetDeltaScroll();
|
||||
finishAnimations();
|
||||
|
||||
// Initialize the velocity tracker
|
||||
initOrResetVelocityTracker();
|
||||
mVelocityTracker.addMovement(ev);
|
||||
@@ -431,8 +445,18 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
||||
public boolean canChildBeDismissed(View v) {
|
||||
// Disallow dismissing an already dismissed task
|
||||
TaskView tv = (TaskView) v;
|
||||
Task task = tv.getTask();
|
||||
return !mSwipeHelperAnimations.containsKey(v) &&
|
||||
(mSv.getStack().indexOfStackTask(tv.getTask()) != -1);
|
||||
(mSv.getStack().indexOfStackTask(task) != -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a manual drag that goes through the same swipe helper path.
|
||||
*/
|
||||
public void onBeginManualDrag(TaskView v) {
|
||||
mActiveTaskView = v;
|
||||
mSwipeHelperAnimations.put(v, null);
|
||||
onBeginDrag(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -453,7 +477,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
||||
mSv.addIgnoreTask(tv.getTask());
|
||||
|
||||
// Determine if we are animating the other tasks while dismissing this task
|
||||
mCurrentTasks = mSv.getStack().getStackTasks();
|
||||
mCurrentTasks = new ArrayList<Task>(mSv.getStack().getStackTasks());
|
||||
MutableBoolean isFrontMostTask = new MutableBoolean(false);
|
||||
Task anchorTask = mSv.findAnchorTask(mCurrentTasks, isFrontMostTask);
|
||||
TaskStackLayoutAlgorithm layoutAlgorithm = mSv.getStackAlgorithm();
|
||||
@@ -513,7 +537,12 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
||||
|
||||
@Override
|
||||
public boolean updateSwipeProgress(View v, boolean dismissable, float swipeProgress) {
|
||||
updateTaskViewTransforms(Interpolators.FAST_OUT_SLOW_IN.getInterpolation(swipeProgress));
|
||||
// Only update the swipe progress for the surrounding tasks if the dismiss animation was not
|
||||
// preempted from a call to cancelNonDismissTaskAnimations
|
||||
if (mActiveTaskView == v || mSwipeHelperAnimations.containsKey(v)) {
|
||||
updateTaskViewTransforms(
|
||||
Interpolators.FAST_OUT_SLOW_IN.getInterpolation(swipeProgress));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -528,15 +557,24 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
||||
tv.setClipViewInStack(true);
|
||||
// Re-enable touch events from this task view
|
||||
tv.setTouchEnabled(true);
|
||||
// Remove the task view from the stack
|
||||
EventBus.getDefault().send(new TaskViewDismissedEvent(tv.getTask(), tv));
|
||||
// Update the scroll to the final scroll position from onBeginDrag()
|
||||
mSv.getScroller().setStackScroll(mTargetStackScroll, null);
|
||||
// Update the focus state to the final focus state
|
||||
mSv.getStackAlgorithm().setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
|
||||
mSv.getStackAlgorithm().clearUnfocusedTaskOverrides();
|
||||
// Stop tracking this deletion animation
|
||||
mSwipeHelperAnimations.remove(v);
|
||||
// Remove the task view from the stack, ignoring the animation if we've started dragging
|
||||
// again
|
||||
EventBus.getDefault().send(new TaskViewDismissedEvent(tv.getTask(), tv,
|
||||
mSwipeHelperAnimations.containsKey(v)
|
||||
? new AnimationProps(TaskStackView.DEFAULT_SYNC_STACK_DURATION,
|
||||
Interpolators.FAST_OUT_SLOW_IN)
|
||||
: null));
|
||||
// Only update the final scroll and layout state (set in onBeginDrag()) if the dismiss
|
||||
// animation was not preempted from a call to cancelNonDismissTaskAnimations
|
||||
if (mSwipeHelperAnimations.containsKey(v)) {
|
||||
// Update the scroll to the final scroll position
|
||||
mSv.getScroller().setStackScroll(mTargetStackScroll, null);
|
||||
// Update the focus state to the final focus state
|
||||
mSv.getStackAlgorithm().setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
|
||||
mSv.getStackAlgorithm().clearUnfocusedTaskOverrides();
|
||||
// Stop tracking this deletion animation
|
||||
mSwipeHelperAnimations.remove(v);
|
||||
}
|
||||
// Keep track of deletions by keyboard
|
||||
MetricsLogger.histogram(tv.getContext(), "overview_task_dismissed_source",
|
||||
Constants.Metrics.DismissSourceSwipeGesture);
|
||||
@@ -631,7 +669,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
|
||||
/**
|
||||
* Returns the scaled size used to calculate the dismiss fraction.
|
||||
*/
|
||||
private float getScaledDismissSize() {
|
||||
public float getScaledDismissSize() {
|
||||
return 1.5f * Math.max(mSv.getWidth(), mSv.getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,7 +388,9 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
|
||||
dismissEvent.addPostAnimationCallback(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
EventBus.getDefault().send(new TaskViewDismissedEvent(mTask, tv));
|
||||
EventBus.getDefault().send(new TaskViewDismissedEvent(mTask, tv,
|
||||
new AnimationProps(TaskStackView.DEFAULT_SYNC_STACK_DURATION,
|
||||
Interpolators.FAST_OUT_SLOW_IN)));
|
||||
}
|
||||
});
|
||||
EventBus.getDefault().send(dismissEvent);
|
||||
|
||||
Reference in New Issue
Block a user