OSDN Git Service

Adding desired undocking animation.
authorWinson <winsonc@google.com>
Fri, 15 Apr 2016 18:19:07 +0000 (11:19 -0700)
committerWinson <winsonc@google.com>
Tue, 19 Apr 2016 01:19:06 +0000 (18:19 -0700)
- Separating task binding from task data updating
- Removing unused parameters

Bug: 27154882
Change-Id: Ia970597d57857a74b5d008e91a93703d8fb70c1e

14 files changed:
packages/SystemUI/res/layout/recents_stack_action_button.xml
packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
packages/SystemUI/src/com/android/systemui/recents/events/activity/MultiWindowStateChangedEvent.java
packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java

index 625e9c1..43b3de1 100644 (file)
@@ -32,4 +32,5 @@
     android:shadowRadius="5"
     android:fontFamily="sans-serif-medium"
     android:background="?android:selectableItemBackground"
-    android:visibility="invisible" />
+    android:visibility="invisible"
+    android:forceHasOverlappingRendering="false" />
index 4d69280..a58e12e 100644 (file)
@@ -349,7 +349,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
         loader.loadTasks(this, loadPlan, loadOpts);
         TaskStack stack = loadPlan.getTaskStack();
         mRecentsView.onReload(mIsVisible, stack.getTaskCount() == 0);
-        mRecentsView.updateStack(stack);
+        mRecentsView.updateStack(stack, true /* setStackViewTasks */);
 
         // Update the nav bar scrim, but defer the animation until the enter-window event
         boolean animateNavBarScrim = !launchState.launchedViaDockGesture;
@@ -455,13 +455,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
 
         EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
                 false /* fromDeviceOrientationChange */, numStackTasks > 0));
-
-        if (mRecentsView != null) {
-            mRecentsView.updateStack(stack);
-        }
-
-        EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode,
-                numStackTasks > 0));
+        EventBus.getDefault().send(new MultiWindowStateChangedEvent(isInMultiWindowMode, stack));
     }
 
     @Override
index 0413bc9..e192da7 100644 (file)
@@ -771,8 +771,9 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
                     if (icon != null) {
                         icon.setCallback(null);
                     }
-                    mHeaderBar.rebindToTask(toTask, false /* touchExplorationEnabled */,
+                    mHeaderBar.bindToTask(toTask, false /* touchExplorationEnabled */,
                             disabledInSafeMode);
+                    mHeaderBar.onTaskDataLoaded();
                     mHeaderBar.setDimAlpha(toTransform.dimAlpha);
                     mHeaderBar.draw(c);
                     c.setBitmap(null);
index cf2a68e..11649fb 100644 (file)
 package com.android.systemui.recents.events.activity;
 
 import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.model.TaskStack;
 
 /**
  * This is sent by the activity whenever the multi-window state has changed.
  */
-public class MultiWindowStateChangedEvent extends EventBus.Event {
+public class MultiWindowStateChangedEvent extends EventBus.AnimatedEvent {
 
     public final boolean inMultiWindow;
-    public final boolean hasStackTasks;
+    public final TaskStack stack;
 
-    public MultiWindowStateChangedEvent(boolean inMultiWindow, boolean hasStackTasks) {
+    public MultiWindowStateChangedEvent(boolean inMultiWindow, TaskStack stack) {
         this.inMultiWindow = inMultiWindow;
-        this.hasStackTasks = hasStackTasks;
+        this.stack = stack;
     }
 }
index 82c81ae..fb92971 100644 (file)
@@ -353,23 +353,15 @@ public class RecentsTaskLoader {
 
     /**
      * Acquires the task resource data directly from the cache, loading if necessary.
-     *
-     * @param fetchAndInvalidateThumbnails If set, will try loading thumbnails, invalidating them
-     *                                     in the cache and loading if necessary. Otherwise, do not
-     *                                     load the thumbnail unless the icon also has to be loaded.
      */
-    public void loadTaskData(Task t, boolean fetchAndInvalidateThumbnails) {
+    public void loadTaskData(Task t) {
         Drawable icon = mIconCache.getAndInvalidateIfModified(t.key);
         Bitmap thumbnail = null;
         ActivityManager.TaskThumbnailInfo thumbnailInfo = null;
-        if (fetchAndInvalidateThumbnails) {
-            ThumbnailData thumbnailData = mThumbnailCache.getAndInvalidateIfModified(t.key);
-            if (thumbnailData != null) {
-                thumbnail = thumbnailData.thumbnail;
-                thumbnailInfo = thumbnailData.thumbnailInfo;
-            }
-        } else {
-            thumbnail = mDefaultThumbnail;
+        ThumbnailData thumbnailData = mThumbnailCache.getAndInvalidateIfModified(t.key);
+        if (thumbnailData != null) {
+            thumbnail = thumbnailData.thumbnail;
+            thumbnailInfo = thumbnailData.thumbnailInfo;
         }
 
         // Grab the thumbnail/icon from the cache, if either don't exist, then trigger a reload and
index d55c7d8..6604ccc 100644 (file)
@@ -57,6 +57,7 @@ import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEve
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
 import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskEvent;
+import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
 import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
 import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
 import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
@@ -143,7 +144,6 @@ public class RecentsView extends FrameLayout {
                     R.dimen.recents_task_view_rounded_corners_radius);
             mStackActionButton = (TextView) inflater.inflate(R.layout.recents_stack_action_button,
                     this, false);
-            mStackActionButton.forceHasOverlappingRendering(false);
             mStackActionButton.setOnClickListener(new View.OnClickListener() {
                 @Override
                 public void onClick(View v) {
@@ -203,9 +203,11 @@ public class RecentsView extends FrameLayout {
     /**
      * Called from RecentsActivity when the task stack is updated.
      */
-    public void updateStack(TaskStack stack) {
+    public void updateStack(TaskStack stack, boolean setStackViewTasks) {
         mStack = stack;
-        mTaskStackView.setTasks(stack, true /* allowNotifyStackChanges */);
+        if (setStackViewTasks) {
+            mTaskStackView.setTasks(stack, true /* allowNotifyStackChanges */);
+        }
 
         // Update the top level view's visibilities
         if (stack.getTaskCount() > 0) {
@@ -622,6 +624,10 @@ public class RecentsView extends FrameLayout {
         hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, true /* translate */);
     }
 
+    public final void onBusEvent(MultiWindowStateChangedEvent event) {
+        updateStack(event.stack, false /* setStackViewTasks */);
+    }
+
     /**
      * Shows the stack action button.
      */
index dce2353..06a2c1e 100644 (file)
@@ -146,7 +146,7 @@ public class SystemBarScrimViews {
     }
 
     public final void onBusEvent(MultiWindowStateChangedEvent event) {
-        animateScrimToCurrentNavBarState(event.hasStackTasks);
+        animateScrimToCurrentNavBarState(event.stack.getStackTaskCount() > 0);
     }
 
     /**
index 665d9ad..e79306f 100644 (file)
@@ -485,7 +485,7 @@ public class TaskStackAnimationHelper {
 
         // Get the final set of task transforms
         mStackView.getLayoutTaskTransforms(newScroll, stackLayout.getFocusState(), stackTasks,
-                mTmpFinalTaskTransforms);
+                true /* ignoreTaskOverrides */, mTmpFinalTaskTransforms);
 
         // Focus the task view
         TaskView newFocusedTaskView = mStackView.getChildViewForTask(newFocusedTask);
@@ -529,7 +529,7 @@ public class TaskStackAnimationHelper {
             int duration;
             Interpolator interpolator;
             if (willScrollToFront) {
-                duration = Math.max(100, 100 + ((i - 1) * 50));
+                duration = calculateStaggeredAnimDuration(i);
                 interpolator = FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR;
             } else {
                 if (i < newFocusTaskViewIndex) {
@@ -553,4 +553,100 @@ public class TaskStackAnimationHelper {
         }
         return willScroll;
     }
+
+    /**
+     * Starts the animation to go to the initial stack layout with a task focused.  In addition, the
+     * previous task will be animated in after the scroll completes.
+     */
+    public void startNewStackScrollAnimation(TaskStack newStack,
+            ReferenceCountedTrigger animationTrigger) {
+        TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
+        TaskStackViewScroller stackScroller = mStackView.getScroller();
+
+        // Get the current set of task transforms
+        ArrayList<Task> stackTasks = newStack.getStackTasks();
+        mStackView.getCurrentTaskTransforms(stackTasks, mTmpCurrentTaskTransforms);
+
+        // Update the stack
+        mStackView.setTasks(newStack, false /* allowNotifyStackChanges */);
+        mStackView.updateLayoutAlgorithm(false /* boundScroll */);
+
+        // Pick up the newly visible views after the scroll
+        final float newScroll = stackLayout.mInitialScrollP;
+        mStackView.bindVisibleTaskViews(newScroll);
+
+        // Update the internal state
+        stackLayout.setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
+        stackLayout.setTaskOverridesForInitialState(newStack, true /* ignoreScrollToFront */);
+        stackScroller.setStackScroll(newScroll);
+        mStackView.cancelDeferredTaskViewLayoutAnimation();
+
+        // Get the final set of task transforms
+        mStackView.getLayoutTaskTransforms(newScroll, stackLayout.getFocusState(), stackTasks,
+                false /* ignoreTaskOverrides */, mTmpFinalTaskTransforms);
+
+        // Hide the front most task view until the scroll is complete
+        Task frontMostTask = newStack.getStackFrontMostTask(false /* includeFreeform */);
+        final TaskView frontMostTaskView = mStackView.getChildViewForTask(frontMostTask);
+        final TaskViewTransform frontMostTransform = mTmpFinalTaskTransforms.get(
+                stackTasks.indexOf(frontMostTask));
+        if (frontMostTaskView != null) {
+            mStackView.updateTaskViewToTransform(frontMostTaskView,
+                    stackLayout.getFrontOfStackTransform(), AnimationProps.IMMEDIATE);
+        }
+
+        // Setup the end listener to return all the hidden views to the view pool after the
+        // focus animation
+        animationTrigger.addLastDecrementRunnable(new Runnable() {
+            @Override
+            public void run() {
+                mStackView.bindVisibleTaskViews(newScroll);
+
+                // Now, animate in the front-most task
+                if (frontMostTaskView != null) {
+                    mStackView.updateTaskViewToTransform(frontMostTaskView, frontMostTransform,
+                            new AnimationProps(75, 200, FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR));
+                }
+            }
+        });
+
+        List<TaskView> taskViews = mStackView.getTaskViews();
+        int taskViewCount = taskViews.size();
+        for (int i = 0; i < taskViewCount; i++) {
+            TaskView tv = taskViews.get(i);
+            Task task = tv.getTask();
+
+            if (mStackView.isIgnoredTask(task)) {
+                continue;
+            }
+            if (task == frontMostTask && frontMostTaskView != null) {
+                continue;
+            }
+
+            int taskIndex = stackTasks.indexOf(task);
+            TaskViewTransform fromTransform = mTmpCurrentTaskTransforms.get(taskIndex);
+            TaskViewTransform toTransform = mTmpFinalTaskTransforms.get(taskIndex);
+
+            // Update the task to the initial state (for the newly picked up tasks)
+            mStackView.updateTaskViewToTransform(tv, fromTransform, AnimationProps.IMMEDIATE);
+
+            int duration = calculateStaggeredAnimDuration(i);
+            Interpolator interpolator = FOCUS_BEHIND_NEXT_TASK_INTERPOLATOR;
+
+            AnimationProps anim = new AnimationProps()
+                    .setDuration(AnimationProps.BOUNDS, duration)
+                    .setInterpolator(AnimationProps.BOUNDS, interpolator)
+                    .setListener(animationTrigger.decrementOnAnimationEnd());
+            animationTrigger.increment();
+            mStackView.updateTaskViewToTransform(tv, toTransform, anim);
+        }
+    }
+
+    /**
+     * Caclulates a staggered duration for {@link #startScrollToFocusedTaskAnimation} and
+     * {@link #startNewStackScrollAnimation}.
+     */
+    private int calculateStaggeredAnimDuration(int i) {
+        return Math.max(100, 100 + ((i - 1) * 50));
+    }
 }
index 34d6bce..57c2bc0 100644 (file)
@@ -577,7 +577,7 @@ public class TaskStackLayoutAlgorithm {
     /**
      * Creates task overrides to ensure the initial stack layout if necessary.
      */
-    public void setTaskOverridesForInitialState(TaskStack stack) {
+    public void setTaskOverridesForInitialState(TaskStack stack, boolean ignoreScrollToFront) {
         RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
 
         mTaskIndexOverrideMap.clear();
@@ -585,7 +585,7 @@ public class TaskStackLayoutAlgorithm {
         boolean scrollToFront = launchState.launchedFromHome ||
                 launchState.launchedViaDockGesture;
         if (getInitialFocusState() == STATE_UNFOCUSED && mNumStackTasks > 1) {
-            if (!launchState.launchedWithAltTab && !scrollToFront) {
+            if (ignoreScrollToFront || (!launchState.launchedWithAltTab && !scrollToFront)) {
                 // Set the initial scroll to the predefined state (which differs from the stack)
                 float [] initialNormX = new float[] {
                         getNormalizedXFromUnfocusedY(mSystemInsets.bottom + mInitialBottomOffset,
@@ -938,7 +938,11 @@ public class TaskStackLayoutAlgorithm {
      * stack.
      */
     float getStackScrollForTask(Task t) {
-        return mTaskIndexOverrideMap.get(t.key.id, (float) mTaskIndexMap.get(t.key.id, 0));
+        Float overrideP = mTaskIndexOverrideMap.get(t.key.id, null);
+        if (overrideP == null) {
+            return (float) mTaskIndexMap.get(t.key.id, 0);
+        }
+        return overrideP;
     }
 
     /**
index a75d1e1..068596b 100644 (file)
@@ -328,6 +328,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
      */
     public void setTasks(TaskStack stack, boolean allowNotifyStackChanges) {
         boolean isInitialized = mLayoutAlgorithm.isInitialized();
+
         // Only notify if we are already initialized, otherwise, everything will pick up all the
         // new and old tasks when we next layout
         mStack.setTasks(getContext(), stack.computeAllTasksList(),
@@ -344,7 +345,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
      */
     public void updateToInitialState() {
         mStackScroller.setStackScrollToInitialState();
-        mLayoutAlgorithm.setTaskOverridesForInitialState(mStack);
+        mLayoutAlgorithm.setTaskOverridesForInitialState(mStack, false /* ignoreScrollToFront */);
     }
 
     /** Updates the list of task views */
@@ -508,11 +509,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
      * Binds the visible {@link TaskView}s at the given target scroll.
      */
     void bindVisibleTaskViews(float targetStackScroll) {
-        bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, false /* ignoreTaskOverrides */);
-    }
-
-    void bindVisibleTaskViews(float targetStackScroll, boolean ignoreTaskOverrides) {
-        bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, ignoreTaskOverrides);
+        bindVisibleTaskViews(targetStackScroll, false /* ignoreTaskOverrides */);
     }
 
     /**
@@ -525,17 +522,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
      * @param targetStackScroll If provided, will ensure that the set of visible {@link TaskView}s
      *                          includes those visible at the current stack scroll, and all at the
      *                          target stack scroll.
-     * @param ignoreTasksSet The set of tasks to ignore in this rebinding of the visible
-     *                       {@link TaskView}s
      * @param ignoreTaskOverrides If set, the visible task computation will get the transforms for
      *                            tasks at their non-overridden task progress
      */
-    void bindVisibleTaskViews(float targetStackScroll, ArraySet<Task.TaskKey> ignoreTasksSet,
-            boolean ignoreTaskOverrides) {
+    void bindVisibleTaskViews(float targetStackScroll, boolean ignoreTaskOverrides) {
         // Get all the task transforms
         ArrayList<Task> tasks = mStack.getStackTasks();
         int[] visibleTaskRange = computeVisibleTaskTransforms(mCurrentTaskTransforms, tasks,
-                mStackScroller.getStackScroll(), targetStackScroll, ignoreTasksSet,
+                mStackScroller.getStackScroll(), targetStackScroll, mIgnoreTasks,
                 ignoreTaskOverrides);
 
         // Return all the invisible children to the pool
@@ -548,7 +542,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
             Task task = tv.getTask();
 
             // Skip ignored tasks
-            if (ignoreTasksSet.contains(task.key)) {
+            if (mIgnoreTasks.contains(task.key)) {
                 continue;
             }
 
@@ -578,7 +572,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
             TaskViewTransform transform = mCurrentTaskTransforms.get(i);
 
             // Skip ignored tasks
-            if (ignoreTasksSet.contains(task.key)) {
+            if (mIgnoreTasks.contains(task.key)) {
                 continue;
             }
 
@@ -626,10 +620,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
     }
 
     /**
-     * @see #relayoutTaskViews(AnimationProps, ArraySet<Task.TaskKey>, boolean)
+     * @see #relayoutTaskViews(AnimationProps, boolean)
      */
     public void relayoutTaskViews(AnimationProps animation) {
-        relayoutTaskViews(animation, mIgnoreTasks, false /* ignoreTaskOverrides */);
+        relayoutTaskViews(animation, false /* ignoreTaskOverrides */);
     }
 
     /**
@@ -637,16 +631,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
      * {@link TaskStackLayoutAlgorithm} with the given {@param animation}. This call cancels any
      * animations that are current running on those task views, and will ensure that the children
      * {@link TaskView}s will match the set of visible tasks in the stack.
-     *
-     * @param ignoreTasksSet the set of tasks to ignore in the relayout
      */
-    private void relayoutTaskViews(AnimationProps animation, ArraySet<Task.TaskKey> ignoreTasksSet,
-            boolean ignoreTaskOverrides) {
+    private void relayoutTaskViews(AnimationProps animation, boolean ignoreTaskOverrides) {
         // If we had a deferred animation, cancel that
         mDeferredTaskViewLayoutAnimation = null;
 
         // Synchronize the current set of TaskViews
-        bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTasksSet,
+        bindVisibleTaskViews(mStackScroller.getStackScroll(),
                 ignoreTaskOverrides /* ignoreTaskOverrides */);
 
         // Animate them to their final transforms with the given animation
@@ -657,7 +648,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
             int taskIndex = mStack.indexOfStackTask(tv.getTask());
             TaskViewTransform transform = mCurrentTaskTransforms.get(taskIndex);
 
-            if (ignoreTasksSet.contains(tv.getTask().key)) {
+            if (mIgnoreTasks.contains(tv.getTask().key)) {
                 continue;
             }
 
@@ -715,13 +706,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
      * {@param stackScroll} and {@param focusState}.
      */
     public void getLayoutTaskTransforms(float stackScroll, int focusState, ArrayList<Task> tasks,
-            ArrayList<TaskViewTransform> transformsOut) {
+            boolean ignoreTaskOverrides, ArrayList<TaskViewTransform> transformsOut) {
         Utilities.matchTaskListSize(tasks, transformsOut);
         for (int i = tasks.size() - 1; i >= 0; i--) {
             Task task = tasks.get(i);
             TaskViewTransform transform = transformsOut.get(i);
             mLayoutAlgorithm.getStackTransform(task, stackScroll, focusState, transform, null,
-                    true /* forceUpdate */, true /* ignoreTaskOverrides */);
+                    true /* forceUpdate */, ignoreTaskOverrides);
             transform.visible = true;
         }
     }
@@ -812,22 +803,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
 
     /**
      * Updates the layout algorithm min and max virtual scroll bounds.
-     *
-     * @see #updateLayoutAlgorithm(boolean, ArraySet<Task.TaskKey>)
      */
    public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax) {
-        updateLayoutAlgorithm(boundScrollToNewMinMax, mIgnoreTasks);
-    }
-
-    /**
-     * Updates the min and max virtual scroll bounds.
-     *
-     * @param ignoreTasksSet the set of tasks to ignore in the relayout
-     */
-    private void updateLayoutAlgorithm(boolean boundScrollToNewMinMax,
-            ArraySet<Task.TaskKey> ignoreTasksSet) {
         // Compute the min and max scroll values
-        mLayoutAlgorithm.update(mStack, ignoreTasksSet);
+        mLayoutAlgorithm.update(mStack, mIgnoreTasks);
 
         // Update the freeform workspace background
         SystemServicesProxy ssp = Recents.getSystemServices();
@@ -1195,8 +1174,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
         }
 
         // Rebind all the views, including the ignore ones
-        bindVisibleTaskViews(mStackScroller.getStackScroll(), mIgnoreTasks,
-                false /* ignoreTaskOverrides */);
+        bindVisibleTaskViews(mStackScroller.getStackScroll(), false /* ignoreTaskOverrides */);
 
         // Measure each of the TaskViews
         mTmpTaskViews.clear();
@@ -1553,7 +1531,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
         tv.onTaskBound(task);
 
         // Load the task data
-        Recents.getTaskLoader().loadTaskData(task, true /* fetchAndInvalidateThumbnails */);
+        Recents.getTaskLoader().loadTaskData(task);
     }
 
     private void unbindTaskView(TaskView tv, Task task) {
@@ -1834,7 +1812,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
             updateLayoutAlgorithm(true /* boundScroll */);
             addIgnoreTask(event.task);
         }
-        relayoutTaskViews(animation, mIgnoreTasks, ignoreTaskOverrides);
+        relayoutTaskViews(animation, ignoreTaskOverrides);
     }
 
     public final void onBusEvent(final DragEndEvent event) {
@@ -1948,26 +1926,24 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
         }
     }
 
-    public final void onBusEvent(MultiWindowStateChangedEvent event) {
-        if (!event.inMultiWindow) {
+    public final void onBusEvent(final MultiWindowStateChangedEvent event) {
+        if (event.inMultiWindow) {
+            setTasks(event.stack, true /* allowNotifyStackChanges */);
+        } else {
+            // Reset the launch state before handling the multiwindow change
+            RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+            launchState.reset();
+
             // Defer until the next frame to ensure that we have received all the system insets, and
             // initial layout updates
+            event.getAnimationTrigger().increment();
             post(new Runnable() {
                 @Override
                 public void run() {
                     // Scroll the stack to the front to see the undocked task
-                    mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP, new Runnable() {
-                        @Override
-                        public void run() {
-                            List<TaskView> taskViews = getTaskViews();
-                            int taskViewCount = taskViews.size();
-                            for (int i = 0; i < taskViewCount; i++) {
-                                TaskView tv = taskViews.get(i);
-                                tv.getHeaderView().rebindToTask(tv.getTask(),
-                                        tv.mTouchExplorationEnabled, tv.mIsDisabledInSafeMode);
-                            }
-                        }
-                    });
+                    mAnimationHelper.startNewStackScrollAnimation(event.stack,
+                            event.getAnimationTrigger());
+                    event.getAnimationTrigger().decrement();
                 }
             });
         }
index 3cdb1fb..4441ddc 100644 (file)
@@ -483,7 +483,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
 
             // Get the final set of task transforms (with task removed)
             mSv.getLayoutTaskTransforms(newStackScroll, TaskStackLayoutAlgorithm.STATE_UNFOCUSED,
-                    mCurrentTasks, mFinalTaskTransforms);
+                    mCurrentTasks, true /* ignoreTaskOverrides */, mFinalTaskTransforms);
 
             // Set the target to scroll towards upon dismissal
             mTargetStackScroll = newStackScroll;
index 37f5a9f..7ea70b5 100644 (file)
@@ -24,13 +24,9 @@ import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.app.ActivityManager;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Outline;
-import android.graphics.Paint;
 import android.graphics.Point;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
@@ -607,6 +603,8 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
         mTask = t;
         mTask.addCallback(this);
         mIsDisabledInSafeMode = !mTask.isSystemApp && ssp.isInSafeMode();
+        mThumbnailView.bindToTask(mTask, mIsDisabledInSafeMode);
+        mHeaderView.bindToTask(mTask, mTouchExplorationEnabled, mIsDisabledInSafeMode);
 
         if (!t.isDockable && ssp.hasDockedTask()) {
             if (mIncompatibleAppToastView == null) {
@@ -623,15 +621,15 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
 
     @Override
     public void onTaskDataLoaded(Task task, ActivityManager.TaskThumbnailInfo thumbnailInfo) {
-        // Bind each of the views to the new task data
-        mThumbnailView.rebindToTask(mTask, thumbnailInfo, mIsDisabledInSafeMode);
-        mHeaderView.rebindToTask(mTask, mTouchExplorationEnabled, mIsDisabledInSafeMode);
+        // Update each of the views to the new task data
+        mThumbnailView.onTaskDataLoaded(thumbnailInfo);
+        mHeaderView.onTaskDataLoaded();
         mTaskDataLoaded = true;
     }
 
     @Override
     public void onTaskDataUnloaded() {
-        // Unbind each of the views from the task data and remove the task callback
+        // Unbind each of the views from the task and remove the task callback
         mTask.removeCallback(this);
         mThumbnailView.unbindFromTask();
         mHeaderView.unbindFromTask(mTouchExplorationEnabled);
@@ -640,7 +638,9 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
 
     @Override
     public void onTaskStackIdChanged() {
-        mHeaderView.rebindToTask(mTask, mTouchExplorationEnabled, mIsDisabledInSafeMode);
+        // Force rebind the header, the thumbnail does not change due to stack changes
+        mHeaderView.bindToTask(mTask, mTouchExplorationEnabled, mIsDisabledInSafeMode);
+        mHeaderView.onTaskDataLoaded();
     }
 
     /**** View.OnClickListener Implementation ****/
index fb0fc30..aac6d13 100644 (file)
@@ -438,21 +438,18 @@ public class TaskViewHeader extends FrameLayout
         }
     }
 
-    /** Binds the bar view to the task */
-    public void rebindToTask(Task t, boolean touchExplorationEnabled, boolean disabledInSafeMode) {
+    /**
+     * Binds the bar view to the task.
+     */
+    public void bindToTask(Task t, boolean touchExplorationEnabled, boolean disabledInSafeMode) {
         mTask = t;
 
-        // If an activity icon is defined, then we use that as the primary icon to show in the bar,
-        // otherwise, we fall back to the application icon
         int primaryColor = disabledInSafeMode
                 ? mDisabledTaskBarBackgroundColor
                 : t.colorPrimary;
         if (mBackground.getColor() != primaryColor) {
             updateBackgroundColor(primaryColor, mDimAlpha);
         }
-        if (t.icon != null) {
-            mIconView.setImageDrawable(t.icon);
-        }
         if (!mTitleView.getText().toString().equals(t.title)) {
             mTitleView.setText(t.title);
         }
@@ -497,6 +494,16 @@ public class TaskViewHeader extends FrameLayout
         }
     }
 
+    /**
+     * Called when the bound task's data has loaded and this view should update to reflect the
+     * changes.
+     */
+    public void onTaskDataLoaded() {
+        if (mTask.icon != null) {
+            mIconView.setImageDrawable(mTask.icon);
+        }
+    }
+
     /** Unbinds the bar view from the task */
     void unbindFromTask(boolean touchExplorationEnabled) {
         mTask = null;
index 4de7713..8977f50 100644 (file)
@@ -302,21 +302,29 @@ public class TaskViewThumbnail extends View {
         updateThumbnailPaintFilter();
     }
 
-    /** Binds the thumbnail view to the task */
-    void rebindToTask(Task t, ActivityManager.TaskThumbnailInfo thumbnailInfo,
-            boolean disabledInSafeMode) {
+    /**
+     * Binds the thumbnail view to the task.
+     */
+    void bindToTask(Task t, boolean disabledInSafeMode) {
         mTask = t;
         mDisabledInSafeMode = disabledInSafeMode;
-        if (t.thumbnail != null) {
-            setThumbnail(t.thumbnail, thumbnailInfo);
-        } else {
-            setThumbnail(null, null);
-        }
         if (t.colorBackground != 0) {
             mBgFillPaint.setColor(t.colorBackground);
         }
     }
 
+    /**
+     * Called when the bound task's data has loaded and this view should update to reflect the
+     * changes.
+     */
+    void onTaskDataLoaded(ActivityManager.TaskThumbnailInfo thumbnailInfo) {
+        if (mTask.thumbnail != null) {
+            setThumbnail(mTask.thumbnail, thumbnailInfo);
+        } else {
+            setThumbnail(null, null);
+        }
+    }
+
     /** Unbinds the thumbnail view from the task */
     void unbindFromTask() {
         mTask = null;