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:
Winson Chung
2016-05-03 21:57:01 +00:00
committed by Android (Google) Code Review
10 changed files with 132 additions and 54 deletions

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -193,7 +193,7 @@ public class RecentsViewTouchHandler {
}
public final void onBusEvent(ConfigurationChangedEvent event) {
if (event.fromDisplayDensityChange) {
if (event.fromDisplayDensityChange || event.fromDeviceOrientationChange) {
updateSnapAlgorithm();
}
}

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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());
}
}

View File

@@ -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);