From 67c79578f94646bade5d336af0d4491179c1b37d Mon Sep 17 00:00:00 2001 From: Winson Date: Wed, 13 Apr 2016 14:02:18 -0700 Subject: [PATCH] Fixing various layout issues when docking - Fixing regression where we were scrolling to front immediately on dragging-to-dock a task, we should only scroll to the front on configuration change. - Accounting for the inset when calculating the final stack bounds (similar to b/27921362) - Fixing issue with task views being clipped as user drags a view due to the bounds of the view changing. We manually now set the frame on the view to the current stack task bounds. - Simplifying calls to animate the task view bounds - Removing old instance state code Change-Id: I17d3e33e159ff250c11a504ef87558051926a974 --- .../SystemUI/res/layout/recents_task_view.xml | 70 +++++----- .../systemui/recents/RecentsActivity.java | 16 +-- .../android/systemui/recents/RecentsImpl.java | 4 +- .../activity/ConfigurationChangedEvent.java | 6 +- .../systemui/recents/misc/Utilities.java | 13 +- .../systemui/recents/model/TaskStack.java | 2 +- .../recents/views/FixedSizeFrameLayout.java | 4 + .../systemui/recents/views/RecentsView.java | 4 +- .../views/TaskStackLayoutAlgorithm.java | 61 +++++---- .../systemui/recents/views/TaskStackView.java | 120 +++++++----------- .../systemui/recents/views/TaskView.java | 16 ++- .../recents/views/TaskViewHeader.java | 2 + .../recents/views/TaskViewThumbnail.java | 16 ++- .../recents/views/TaskViewTransform.java | 67 +++------- 14 files changed, 186 insertions(+), 215 deletions(-) diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml index b1b2f1ed34e0e..1978a930b199b 100644 --- a/packages/SystemUI/res/layout/recents_task_view.xml +++ b/packages/SystemUI/res/layout/recents_task_view.xml @@ -18,47 +18,43 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:focusable="true"> - - + android:layout_height="match_parent" /> - + - - - + + + + - - - + + diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index df7966927a57a..4d69280dfa220 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -98,7 +98,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD private RecentsPackageMonitor mPackageMonitor; private long mLastTabKeyEventTime; - private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED; + private int mLastDeviceOrientation = Configuration.ORIENTATION_UNDEFINED; private boolean mFinishedOnStartup; private boolean mIgnoreAltTabRelease; private boolean mIsVisible; @@ -276,7 +276,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD getWindow().getAttributes().privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY; - mLastOrientation = getResources().getConfiguration().orientation; + mLastDeviceOrientation = Utilities.getAppConfiguration(this).orientation; mFocusTimerDuration = getResources().getInteger(R.integer.recents_auto_advance_duration); mIterateTrigger = new DozeTrigger(mFocusTimerDuration, new Runnable() { @Override @@ -426,13 +426,12 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); - // Notify of the config change - int newOrientation = getResources().getConfiguration().orientation; + int newDeviceOrientation = Utilities.getAppConfiguration(this).orientation; int numStackTasks = mRecentsView.getStack().getStackTaskCount(); EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */, - (mLastOrientation != newOrientation), numStackTasks > 0)); - mLastOrientation = newOrientation; + (mLastDeviceOrientation != newDeviceOrientation), numStackTasks > 0)); + mLastDeviceOrientation = newDeviceOrientation; } @Override @@ -455,7 +454,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD int numStackTasks = stack.getStackTaskCount(); EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */, - false /* fromOrientationChange */, numStackTasks > 0)); + false /* fromDeviceOrientationChange */, numStackTasks > 0)); if (mRecentsView != null) { mRecentsView.updateStack(stack); @@ -777,6 +776,8 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD @Override public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { super.dump(prefix, fd, writer, args); + EventBus.getDefault().dump(prefix, writer); + String id = Integer.toHexString(System.identityHashCode(this)); writer.print(prefix); writer.print(TAG); @@ -787,6 +788,5 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD if (mRecentsView != null) { mRecentsView.dump(prefix, writer); } - EventBus.getDefault().dump(prefix, writer); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index 6d32293d7aaad..c230cd8fa400d 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -689,7 +689,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener TaskStackViewScroller stackScroller = stackView.getScroller(); stackView.updateLayoutAlgorithm(true /* boundScroll */); - stackView.updateToInitialState(true /* scrollToInitialState */); + stackView.updateToInitialState(); for (int i = tasks.size() - 1; i >= 0; i--) { Task task = tasks.get(i); @@ -742,7 +742,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener // Get the transform for the running task stackView.updateLayoutAlgorithm(true /* boundScroll */); - stackView.updateToInitialState(true /* scrollToInitialState */); + stackView.updateToInitialState(); stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask, stackView.getScroller().getStackScroll(), mTmpTransform, null); return mTmpTransform; diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java index e3bc2a760b5fa..53b67cfc33db0 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java +++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java @@ -24,13 +24,13 @@ import com.android.systemui.recents.events.EventBus; public class ConfigurationChangedEvent extends EventBus.AnimatedEvent { public final boolean fromMultiWindow; - public final boolean fromOrientationChange; + public final boolean fromDeviceOrientationChange; public final boolean hasStackTasks; - public ConfigurationChangedEvent(boolean fromMultiWindow, boolean fromOrientationChange, + public ConfigurationChangedEvent(boolean fromMultiWindow, boolean fromDeviceOrientationChange, boolean hasStackTasks) { this.fromMultiWindow = fromMultiWindow; - this.fromOrientationChange = fromOrientationChange; + this.fromDeviceOrientationChange = fromDeviceOrientationChange; this.hasStackTasks = hasStackTasks; } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java index 4ecda542ca362..f6cc12bebb129 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java @@ -18,8 +18,11 @@ package com.android.systemui.recents.misc; import android.animation.Animator; import android.animation.AnimatorSet; +import android.animation.RectEvaluator; import android.annotation.FloatRange; import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.Color; import android.graphics.Rect; @@ -71,7 +74,7 @@ public class Utilities { }; public static final RectFEvaluator RECTF_EVALUATOR = new RectFEvaluator(); - + public static final RectEvaluator RECT_EVALUATOR = new RectEvaluator(new Rect()); public static final Rect EMPTY_RECT = new Rect(); /** @@ -269,6 +272,14 @@ public class Utilities { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } + /** + * Returns the application configuration, which is independent of the activity's current + * configuration in multiwindow. + */ + public static Configuration getAppConfiguration(Context context) { + return context.getApplicationContext().getResources().getConfiguration(); + } + /** * Returns a lightweight dump of a rect. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java index fbb59870b2372..95e276f7c8cf8 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java @@ -299,7 +299,7 @@ public class TaskStack { if (bounds != null && !dockAreaOverlay.getBounds().equals(bounds)) { if (animateBounds) { PropertyValuesHolder prop = PropertyValuesHolder.ofObject( - Utilities.DRAWABLE_RECT, new RectEvaluator(new Rect()), + Utilities.DRAWABLE_RECT, Utilities.RECT_EVALUATOR, dockAreaOverlay.getBounds(), bounds); animators.add(ObjectAnimator.ofPropertyValuesHolder(dockAreaOverlay, prop)); } else { diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java index 9f2b00a50e606..471df6ae41fad 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/FixedSizeFrameLayout.java @@ -88,6 +88,10 @@ public class FixedSizeFrameLayout extends FrameLayout { */ protected void layoutContents(Rect bounds, boolean changed) { super.onLayout(changed, bounds.left, bounds.top, bounds.right, bounds.bottom); + + int width = getMeasuredWidth(); + int height = getMeasuredHeight(); + onSizeChanged(width, height, width, height); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 86d68c2b7e9fb..d55c7d80f0ee5 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -519,7 +519,9 @@ public class RecentsView extends FrameLayout { @Override public void onAnimationStarted() { EventBus.getDefault().send(new DockedFirstAnimationFrameEvent()); - mTaskStackView.getStack().removeTask(event.task, AnimationProps.IMMEDIATE, + // Remove the task and don't bother relaying out, as all the tasks will be + // relaid out when the stack changes on the multiwindow change event + mTaskStackView.getStack().removeTask(event.task, null, true /* fromDockGesture */); } }; 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 e4da8b3699142..34d6bcecdee67 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java @@ -297,9 +297,6 @@ public class TaskStackLayoutAlgorithm { private FreePathInterpolator mUnfocusedDimCurveInterpolator; private FreePathInterpolator mFocusedDimCurveInterpolator; - // Indexed from the front of the stack, the normalized x in the unfocused range for each task - private float[] mInitialNormX; - // 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") @@ -406,8 +403,10 @@ public class TaskStackLayoutAlgorithm { /** * Sets the system insets. */ - public void setSystemInsets(Rect systemInsets) { + public boolean setSystemInsets(Rect systemInsets) { + boolean changed = mSystemInsets.equals(systemInsets); mSystemInsets.set(systemInsets); + return changed; } /** @@ -545,13 +544,11 @@ public class TaskStackLayoutAlgorithm { } else { mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP); } - mInitialNormX = null; } else if (!ssp.hasFreeformWorkspaceSupport() && mNumStackTasks == 1) { // If there is one stack task, ignore the min/max/initial scroll positions mMinScrollP = 0; mMaxScrollP = 0; mInitialScrollP = 0; - mInitialNormX = null; } else { // Set the max scroll to be the point where the front most task is visible with the // stack bottom offset @@ -565,42 +562,50 @@ public class TaskStackLayoutAlgorithm { launchState.launchedViaDockGesture; if (launchState.launchedWithAltTab) { mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP); - mInitialNormX = null; } else if (scrollToFront) { mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP); - mInitialNormX = null; } else { // We are overriding the initial two task positions, so set the initial scroll // position to match the second task (aka focused task) position float initialTopNormX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP); mInitialScrollP = Math.max(mMinScrollP, Math.min(mMaxScrollP, (mNumStackTasks - 2)) - Math.max(0, mUnfocusedRange.getAbsoluteX(initialTopNormX))); - - // Set the initial scroll to the predefined state (which differs from the stack) - mInitialNormX = new float[] { - getNormalizedXFromUnfocusedY(mSystemInsets.bottom + mInitialBottomOffset, - FROM_BOTTOM), - initialTopNormX - }; } } } - public void updateToInitialState(List tasks) { - if (mInitialNormX == null) { - return; - } + /** + * Creates task overrides to ensure the initial stack layout if necessary. + */ + public void setTaskOverridesForInitialState(TaskStack stack) { + RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState(); - mUnfocusedRange.offset(0f); - int taskCount = tasks.size(); - for (int i = taskCount - 1; i >= 0; i--) { - int indexFromFront = taskCount - i - 1; - if (indexFromFront >= mInitialNormX.length) { - break; + mTaskIndexOverrideMap.clear(); + + boolean scrollToFront = launchState.launchedFromHome || + launchState.launchedViaDockGesture; + if (getInitialFocusState() == STATE_UNFOCUSED && mNumStackTasks > 1) { + if (!launchState.launchedWithAltTab && !scrollToFront) { + // Set the initial scroll to the predefined state (which differs from the stack) + float [] initialNormX = new float[] { + getNormalizedXFromUnfocusedY(mSystemInsets.bottom + mInitialBottomOffset, + FROM_BOTTOM), + getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP) + }; + + mUnfocusedRange.offset(0f); + List tasks = stack.getStackTasks(); + int taskCount = tasks.size(); + for (int i = taskCount - 1; i >= 0; i--) { + int indexFromFront = taskCount - i - 1; + if (indexFromFront >= initialNormX.length) { + break; + } + float newTaskProgress = mInitialScrollP + + mUnfocusedRange.getAbsoluteX(initialNormX[indexFromFront]); + mTaskIndexOverrideMap.put(tasks.get(i).key.id, newTaskProgress); + } } - float newTaskProgress = mInitialScrollP + - mUnfocusedRange.getAbsoluteX(mInitialNormX[indexFromFront]); - mTaskIndexOverrideMap.put(tasks.get(i).key.id, newTaskProgress); } } 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 63018c548640f..a75d1e1339e29 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -28,11 +28,9 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Rect; -import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; import android.os.Bundle; -import android.os.Parcelable; import android.provider.Settings; import android.util.ArrayMap; import android.util.ArraySet; @@ -105,12 +103,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal private static final String TAG = "TaskStackView"; - private final static String KEY_SAVED_STATE_SUPER = "saved_instance_state_super"; - private final static String KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE = - "saved_instance_state_layout_focused_state"; - private final static String KEY_SAVED_STATE_LAYOUT_STACK_SCROLL = - "saved_instance_state_layout_stack_scroll"; - // The thresholds at which to show/hide the stack action button. private static final float SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD = 0.3f; private static final float HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD = 0.3f; @@ -350,11 +342,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal /** * Updates this TaskStackView to the initial state. */ - public void updateToInitialState(boolean scrollToInitialState) { - if (scrollToInitialState) { - mStackScroller.setStackScrollToInitialState(); - mLayoutAlgorithm.updateToInitialState(mStack.getStackTasks()); - } + public void updateToInitialState() { + mStackScroller.setStackScrollToInitialState(); + mLayoutAlgorithm.setTaskOverridesForInitialState(mStack); } /** Updates the list of task views */ @@ -638,17 +628,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal /** * @see #relayoutTaskViews(AnimationProps, ArraySet, boolean) */ - void relayoutTaskViews(AnimationProps animation) { + public void relayoutTaskViews(AnimationProps animation) { relayoutTaskViews(animation, mIgnoreTasks, false /* ignoreTaskOverrides */); } - /** - * @see #relayoutTaskViews(AnimationProps, ArraySet, boolean) - */ - void relayoutTaskViews(AnimationProps animation, ArraySet ignoreTasksSet) { - relayoutTaskViews(animation, ignoreTasksSet, false /* ignoreTaskOverrides */); - } - /** * Relayout the the visible {@link TaskView}s to their current transforms as specified by the * {@link TaskStackLayoutAlgorithm} with the given {@param animation}. This call cancels any @@ -657,7 +640,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * * @param ignoreTasksSet the set of tasks to ignore in the relayout */ - void relayoutTaskViews(AnimationProps animation, ArraySet ignoreTasksSet, + private void relayoutTaskViews(AnimationProps animation, ArraySet ignoreTasksSet, boolean ignoreTaskOverrides) { // If we had a deferred animation, cancel that mDeferredTaskViewLayoutAnimation = null; @@ -841,7 +824,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * * @param ignoreTasksSet the set of tasks to ignore in the relayout */ - public void updateLayoutAlgorithm(boolean boundScrollToNewMinMax, + private void updateLayoutAlgorithm(boolean boundScrollToNewMinMax, ArraySet ignoreTasksSet) { // Compute the min and max scroll values mLayoutAlgorithm.update(mStack, ignoreTasksSet); @@ -1097,24 +1080,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } } - @Override - protected Parcelable onSaveInstanceState() { - Bundle savedState = new Bundle(); - savedState.putParcelable(KEY_SAVED_STATE_SUPER, super.onSaveInstanceState()); - savedState.putInt(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE, mLayoutAlgorithm.getFocusState()); - savedState.putFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL, mStackScroller.getStackScroll()); - return super.onSaveInstanceState(); - } - - @Override - protected void onRestoreInstanceState(Parcelable state) { - Bundle savedState = (Bundle) state; - super.onRestoreInstanceState(savedState.getParcelable(KEY_SAVED_STATE_SUPER)); - - mLayoutAlgorithm.setFocusState(savedState.getInt(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE)); - mStackScroller.setStackScroll(savedState.getFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL)); - } - @Override public CharSequence getAccessibilityClassName() { return TaskStackView.class.getName(); @@ -1181,9 +1146,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * Updates the system insets. */ public void setSystemInsets(Rect systemInsets) { - if (!systemInsets.equals(mLayoutAlgorithm.mSystemInsets)) { - mStableLayoutAlgorithm.setSystemInsets(systemInsets); - mLayoutAlgorithm.setSystemInsets(systemInsets); + boolean changed = false; + changed |= mStableLayoutAlgorithm.setSystemInsets(systemInsets); + changed |= mLayoutAlgorithm.setSystemInsets(systemInsets); + if (changed) { requestLayout(); } } @@ -1215,12 +1181,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack)); mLayoutAlgorithm.initialize(mWindowRect, mStackBounds, TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack)); - updateLayoutAlgorithm(false /* boundScroll */, mIgnoreTasks); + updateLayoutAlgorithm(false /* boundScroll */); // If this is the first layout, then scroll to the front of the stack, then update the // TaskViews with the stack so that we can lay them out if (mAwaitingFirstLayout || mInitialState != INITIAL_STATE_UPDATE_NONE) { - updateToInitialState(mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY); + if (mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY) { + updateToInitialState(); + } if (!mAwaitingFirstLayout) { mInitialState = INITIAL_STATE_UPDATE_NONE; } @@ -1247,16 +1215,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal * Measures a TaskView. */ private void measureTaskView(TaskView tv) { + Rect padding = new Rect(); if (tv.getBackground() != null) { - tv.getBackground().getPadding(mTmpRect); - } else { - mTmpRect.setEmpty(); + tv.getBackground().getPadding(padding); } - Rect taskRect = mStableLayoutAlgorithm.mTaskRect; + mTmpRect.set(mStableLayoutAlgorithm.mTaskRect); + mTmpRect.union(mLayoutAlgorithm.mTaskRect); tv.measure( - MeasureSpec.makeMeasureSpec(taskRect.width() + mTmpRect.left + mTmpRect.right, + MeasureSpec.makeMeasureSpec(mTmpRect.width() + padding.left + padding.right, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(taskRect.height() + mTmpRect.top + mTmpRect.bottom, + MeasureSpec.makeMeasureSpec(mTmpRect.height() + padding.top + padding.bottom, MeasureSpec.EXACTLY)); } @@ -1278,7 +1246,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } // Relayout all of the task views including the ignored ones - relayoutTaskViews(AnimationProps.IMMEDIATE, mIgnoreTasks); + relayoutTaskViews(AnimationProps.IMMEDIATE); clipTaskViews(); if (mAwaitingFirstLayout || !mEnterAnimationComplete) { @@ -1293,15 +1261,15 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal */ private void layoutTaskView(boolean changed, TaskView tv) { if (changed) { + Rect padding = new Rect(); if (tv.getBackground() != null) { - tv.getBackground().getPadding(mTmpRect); - } else { - mTmpRect.setEmpty(); + tv.getBackground().getPadding(padding); } - Rect taskRect = mStableLayoutAlgorithm.mTaskRect; + mTmpRect.set(mStableLayoutAlgorithm.mTaskRect); + mTmpRect.union(mLayoutAlgorithm.mTaskRect); tv.cancelTransformAnimation(); - tv.layout(taskRect.left - mTmpRect.left, taskRect.top - mTmpRect.top, - taskRect.right + mTmpRect.right, taskRect.bottom + mTmpRect.bottom); + tv.layout(mTmpRect.left - padding.left, mTmpRect.top - padding.top, + mTmpRect.right + padding.right, mTmpRect.bottom + padding.bottom); } else { // If the layout has not changed, then just lay it out again in-place tv.layout(tv.getLeft(), tv.getTop(), tv.getRight(), tv.getBottom()); @@ -1847,7 +1815,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal height -= systemInsets.bottom; systemInsets.bottom = 0; mStackBounds.set(dockState.getDockedTaskStackBounds(getMeasuredWidth(), - height, mDividerSize, mLayoutAlgorithm.mSystemInsets, + height, mDividerSize, systemInsets, mLayoutAlgorithm, getResources(), mWindowRect)); mLayoutAlgorithm.setSystemInsets(systemInsets); mLayoutAlgorithm.initialize(mWindowRect, mStackBounds, @@ -1982,17 +1950,24 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal public final void onBusEvent(MultiWindowStateChangedEvent event) { if (!event.inMultiWindow) { - // Scroll the stack to the front to see the undocked task - mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP, new Runnable() { + // Defer until the next frame to ensure that we have received all the system insets, and + // initial layout updates + post(new Runnable() { @Override public void run() { - List 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); - } + // Scroll the stack to the front to see the undocked task + mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP, new Runnable() { + @Override + public void run() { + List 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); + } + } + }); } }); } @@ -2013,9 +1988,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal } // Trigger a new layout and update to the initial state if necessary - if (event.fromMultiWindow || event.fromOrientationChange) { + if (event.fromMultiWindow) { mInitialState = INITIAL_STATE_UPDATE_LAYOUT_ONLY; requestLayout(); + } else if (event.fromDeviceOrientationChange) { + mInitialState = INITIAL_STATE_UPDATE_ALL; + requestLayout(); } } @@ -2110,7 +2088,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal if (mFocusedTask != null) { writer.print(innerPrefix); writer.print("Focused task: "); - mFocusedTask.dump(innerPrefix, writer); + mFocusedTask.dump("", writer); } mLayoutAlgorithm.dump(innerPrefix, writer); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java index 6be8a4a469bd2..37f5a9fc99747 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -152,7 +152,6 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks private final TaskViewTransform mTargetAnimationTransform = new TaskViewTransform(); private ArrayList mTmpAnimators = new ArrayList<>(); - View mContent; @ViewDebug.ExportedProperty(deepExport=true, prefix="thumbnail_") TaskViewThumbnail mThumbnailView; @ViewDebug.ExportedProperty(deepExport=true, prefix="header_") @@ -226,9 +225,9 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks @Override protected void onFinishInflate() { // Bind the views - mContent = findViewById(R.id.task_view_content); mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar); mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail); + mThumbnailView.updateClipToTaskBar(mHeaderView); mActionButtonView = findViewById(R.id.lock_to_app_fab); mActionButtonView.setOutlineProvider(new ViewOutlineProvider() { @Override @@ -255,6 +254,9 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks if (w > 0 && h > 0) { mHeaderView.onTaskViewSizeChanged(w, h); mThumbnailView.onTaskViewSizeChanged(w, h); + + mActionButtonView.setTranslationX(w - getMeasuredWidth()); + mActionButtonView.setTranslationY(h - getMeasuredHeight()); } } @@ -276,13 +278,11 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks protected void measureContents(int width, int height) { int widthWithoutPadding = width - mPaddingLeft - mPaddingRight; int heightWithoutPadding = height - mPaddingTop - mPaddingBottom; + int widthSpec = MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY); + int heightSpec = MeasureSpec.makeMeasureSpec(heightWithoutPadding, MeasureSpec.EXACTLY); // Measure the content - mContent.measure(MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY), - MeasureSpec.makeMeasureSpec(heightWithoutPadding, MeasureSpec.EXACTLY)); - - // Optimization: Prevent overdraw of the thumbnail under the header view - mThumbnailView.updateClipToTaskBar(mHeaderView); + measureChildren(widthSpec, heightSpec); setMeasuredDimension(width, height); } @@ -346,6 +346,8 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks mActionButtonView.setScaleX(1f); mActionButtonView.setScaleY(1f); mActionButtonView.setAlpha(0f); + mActionButtonView.setTranslationX(0f); + mActionButtonView.setTranslationY(0f); mActionButtonView.setTranslationZ(mActionButtonTranslationZ); if (mIncompatibleAppToastView != null) { mIncompatibleAppToastView.setVisibility(View.INVISIBLE); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java index f98d3d5d23be3..fb0fc3076f304 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -350,6 +350,8 @@ public class TaskViewHeader extends FrameLayout } mDismissButton.setVisibility(showDismissIcon ? View.VISIBLE : View.INVISIBLE); mDismissButton.setTranslationX(rightInset); + + setLeftTopRightBottom(0, 0, width, getMeasuredHeight()); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java index 62fd5858bf9a1..4de7713eb2fb1 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java @@ -123,6 +123,7 @@ public class TaskViewThumbnail extends View { } mTaskViewRect.set(0, 0, width, height); + setLeftTopRightBottom(0, 0, width, height); updateThumbnailScale(); } @@ -148,22 +149,26 @@ public class TaskViewThumbnail extends View { int thumbnailHeight = Math.min(viewHeight, (int) (mThumbnailRect.height() * mThumbnailScale)); if (mBitmapShader != null && thumbnailWidth > 0 && thumbnailHeight > 0) { + int topOffset = mTaskBar != null + ? mTaskBar.getHeight() - mCornerRadius + : 0; + // Draw the background, there will be some small overdraw with the thumbnail if (thumbnailWidth < viewWidth) { // Portrait thumbnail on a landscape task view - canvas.drawRoundRect(Math.max(0, thumbnailWidth - mCornerRadius), 0, + canvas.drawRoundRect(Math.max(0, thumbnailWidth - mCornerRadius), topOffset, viewWidth, viewHeight, mCornerRadius, mCornerRadius, mBgFillPaint); } if (thumbnailHeight < viewHeight) { // Landscape thumbnail on a portrait task view - canvas.drawRoundRect(0, Math.max(0, thumbnailHeight - mCornerRadius), + canvas.drawRoundRect(0, Math.max(topOffset, thumbnailHeight - mCornerRadius), viewWidth, viewHeight, mCornerRadius, mCornerRadius, mBgFillPaint); } // Draw the thumbnail - canvas.drawRoundRect(0, 0, thumbnailWidth, thumbnailHeight, + canvas.drawRoundRect(0, topOffset, thumbnailWidth, thumbnailHeight, mCornerRadius, mCornerRadius, mDrawPaint); } else { canvas.drawRoundRect(0, 0, viewWidth, viewHeight, mCornerRadius, mCornerRadius, @@ -274,10 +279,7 @@ public class TaskViewThumbnail extends View { /** Updates the clip rect based on the given task bar. */ void updateClipToTaskBar(View taskBar) { mTaskBar = taskBar; - int top = (int) Math.max(0, taskBar.getTranslationY() + - taskBar.getMeasuredHeight() - 1); - mClipRect.set(0, top, getMeasuredWidth(), getMeasuredHeight()); - setClipBounds(mClipRect); + invalidate(); } /** Updates the visibility of the the thumbnail. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java index b512393304c3c..397f24eb86d3a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java @@ -19,11 +19,14 @@ package com.android.systemui.recents.views; import android.animation.Animator; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; +import android.graphics.Rect; import android.graphics.RectF; import android.util.IntProperty; import android.util.Property; import android.view.View; +import com.android.systemui.recents.misc.Utilities; + import java.util.ArrayList; /** @@ -31,55 +34,20 @@ import java.util.ArrayList; */ public class TaskViewTransform { - public static final Property LEFT = - new IntProperty("left") { + public static final Property LTRB = + new Property(Rect.class, "leftTopRightBottom") { + + private Rect mTmpRect = new Rect(); + @Override - public void setValue(View object, int v) { - object.setLeft(v); + public void set(View v, Rect ltrb) { + v.setLeftTopRightBottom(ltrb.left, ltrb.top, ltrb.right, ltrb.bottom); } @Override - public Integer get(View object) { - return object.getLeft(); - } - }; - - public static final Property TOP = - new IntProperty("top") { - @Override - public void setValue(View object, int v) { - object.setTop(v); - } - - @Override - public Integer get(View object) { - return object.getTop(); - } - }; - - public static final Property RIGHT = - new IntProperty("right") { - @Override - public void setValue(View object, int v) { - object.setRight(v); - } - - @Override - public Integer get(View object) { - return object.getRight(); - } - }; - - public static final Property BOTTOM = - new IntProperty("bottom") { - @Override - public void setValue(View object, int v) { - object.setBottom(v); - } - - @Override - public Integer get(View object) { - return object.getBottom(); + public Rect get(View v) { + mTmpRect.set(v.getLeft(), v.getTop(), v.getRight(), v.getBottom()); + return mTmpRect; } }; @@ -205,11 +173,12 @@ public class TaskViewTransform { animators.add(animation.apply(AnimationProps.ALPHA, anim)); } if (hasRectChangedFrom(v)) { + Rect fromViewRect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom()); + Rect toViewRect = new Rect(); + rect.round(toViewRect); ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(v, - PropertyValuesHolder.ofInt(LEFT, v.getLeft(), (int) rect.left), - PropertyValuesHolder.ofInt(TOP, v.getTop(), (int) rect.top), - PropertyValuesHolder.ofInt(RIGHT, v.getRight(), (int) rect.right), - PropertyValuesHolder.ofInt(BOTTOM, v.getBottom(), (int) rect.bottom)); + PropertyValuesHolder.ofObject(LTRB, Utilities.RECT_EVALUATOR, + fromViewRect, toViewRect)); animators.add(animation.apply(AnimationProps.BOUNDS, anim)); } }