From 619e40cd56266a362ab7da80cb9e4eba6c33b204 Mon Sep 17 00:00:00 2001 From: Winson Date: Fri, 25 Mar 2016 16:12:35 -0700 Subject: [PATCH] Fix config change layout. (Part 2) - Fixing issue where the initial state was not correct after rotating the screen. We needed to update the layout, but that could only be done after the task stack view is laid out. Now we set a flag to update the initial state of the layout on configuration change, and only scrolling to the front when it makes sense. Change-Id: I2586b90d1e869708b97bcd1a4446f4d87fa521cc --- .../systemui/recents/RecentsActivity.java | 4 +- .../android/systemui/recents/RecentsImpl.java | 4 +- .../activity/ConfigurationChangedEvent.java | 7 ++- .../views/TaskStackLayoutAlgorithm.java | 2 +- .../systemui/recents/views/TaskStackView.java | 51 +++++++++++++++---- .../systemui/recents/views/TaskView.java | 8 +++ .../recents/views/TaskViewHeader.java | 48 ++++++++++------- 7 files changed, 90 insertions(+), 34 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 8536882a35490..fe7ac711e8c13 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -415,13 +415,13 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD // Update the nav bar for the current orientation updateNavBarScrim(false /* animateNavBarScrim */, AnimationProps.IMMEDIATE); - EventBus.getDefault().send(new ConfigurationChangedEvent()); + EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */)); } @Override public void onMultiWindowChanged(boolean inMultiWindow) { super.onMultiWindowChanged(inMultiWindow); - EventBus.getDefault().send(new ConfigurationChangedEvent()); + EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */)); if (mRecentsView != null) { // Reload the task stack completely diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index e6828820ed19a..7daef649adfce 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -708,7 +708,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener TaskStackViewScroller stackScroller = stackView.getScroller(); stackView.updateLayoutAlgorithm(true /* boundScroll */); - stackView.updateToInitialState(); + stackView.updateToInitialState(true /* scrollToInitialState */); for (int i = tasks.size() - 1; i >= 0; i--) { Task task = tasks.get(i); @@ -775,7 +775,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener // Get the transform for the running task stackView.updateLayoutAlgorithm(true /* boundScroll */); - stackView.updateToInitialState(); + stackView.updateToInitialState(true /* scrollToInitialState */); mTmpTransform = 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 0ad46817154fe..c234c348ad66c 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 @@ -22,5 +22,10 @@ import com.android.systemui.recents.events.EventBus; * This is sent when the Recents activity configuration has changed. */ public class ConfigurationChangedEvent extends EventBus.AnimatedEvent { - // Simple event + + public final boolean fromMultiWindow; + + public ConfigurationChangedEvent(boolean fromMultiWindow) { + this.fromMultiWindow = fromMultiWindow; + } } 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 36cdb1c147a6d..8a1727a202717 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java @@ -852,7 +852,7 @@ public class TaskStackLayoutAlgorithm { // in screen space float tmpP = (mMinScrollP - stackScroll) / mNumStackTasks; int centerYOffset = (mStackRect.top - mTaskRect.top) + - (mStackRect.height() - mTaskRect.height()) / 2; + (mStackRect.height() - mSystemInsets.bottom - mTaskRect.height()) / 2; y = centerYOffset + getYForDeltaP(tmpP, 0); z = mMaxTranslationZ; dimAlpha = 0f; 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 5b9dfabe838ac..90328714c51e0 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -22,6 +22,7 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; +import android.annotation.IntDef; import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; @@ -87,6 +88,8 @@ import com.android.systemui.recents.misc.Utilities; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskStack; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; @@ -116,6 +119,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal private static final ArraySet EMPTY_TASK_SET = new ArraySet<>(); + // The actions to perform when resetting to initial state, + @Retention(RetentionPolicy.SOURCE) + @IntDef({INITIAL_STATE_UPDATE_NONE, INITIAL_STATE_UPDATE_ALL, INITIAL_STATE_UPDATE_LAYOUT_ONLY}) + public @interface InitialStateAction {} + /** Do not update the stack and layout to the initial state. */ + private static final int INITIAL_STATE_UPDATE_NONE = 0; + /** Update both the stack and layout to the initial state. */ + private static final int INITIAL_STATE_UPDATE_ALL = 1; + /** Update only the layout to the initial state. */ + private static final int INITIAL_STATE_UPDATE_LAYOUT_ONLY = 2; + LayoutInflater mInflater; TaskStack mStack = new TaskStack(); @ViewDebug.ExportedProperty(deepExport=true, prefix="layout_") @@ -150,6 +164,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal @ViewDebug.ExportedProperty(category="recents") boolean mAwaitingFirstLayout = true; @ViewDebug.ExportedProperty(category="recents") + @InitialStateAction + int mInitialState = INITIAL_STATE_UPDATE_ALL; + @ViewDebug.ExportedProperty(category="recents") boolean mInMeasureLayout = false; @ViewDebug.ExportedProperty(category="recents") boolean mEnterAnimationComplete = false; @@ -307,6 +324,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // Since we always animate to the same place in (the initial state), always reset the stack // to the initial state when resuming mAwaitingFirstLayout = true; + mInitialState = INITIAL_STATE_UPDATE_ALL; requestLayout(); } @@ -329,8 +347,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal /** * Updates this TaskStackView to the initial state. */ - public void updateToInitialState() { - mStackScroller.setStackScrollToInitialState(); + public void updateToInitialState(boolean scrollToInitialState) { + if (scrollToInitialState) { + mStackScroller.setStackScrollToInitialState(); + } mLayoutAlgorithm.updateToInitialState(mStack.getStackTasks()); } @@ -1199,11 +1219,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal // 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 - // TODO: The second check is a workaround for wacky layouts that we get while docking via - // long pressing the recents button - if (mAwaitingFirstLayout || - (mStackScroller.getStackScroll() == mLayoutAlgorithm.mInitialScrollP)) { - updateToInitialState(); + if (mAwaitingFirstLayout || mInitialState != INITIAL_STATE_UPDATE_NONE) { + updateToInitialState(mInitialState != INITIAL_STATE_UPDATE_LAYOUT_ONLY); + mInitialState = INITIAL_STATE_UPDATE_NONE; } // Rebind all the views, including the ignore ones @@ -1916,8 +1934,23 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal public final void onBusEvent(ConfigurationChangedEvent event) { mStableLayoutAlgorithm.reloadOnConfigurationChange(getContext()); mLayoutAlgorithm.reloadOnConfigurationChange(getContext()); - mLayoutAlgorithm.initialize(mWindowRect, mStackBounds, - TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack)); + + // Notify the task views of the configuration change so they can reload their resources + if (!event.fromMultiWindow) { + mTmpTaskViews.clear(); + mTmpTaskViews.addAll(getTaskViews()); + mTmpTaskViews.addAll(mViewPool.getViews()); + int taskViewCount = mTmpTaskViews.size(); + for (int i = 0; i < taskViewCount; i++) { + mTmpTaskViews.get(i).onConfigurationChanged(); + } + } + + // Trigger a new layout and scroll to the initial state + mInitialState = event.fromMultiWindow + ? INITIAL_STATE_UPDATE_ALL + : INITIAL_STATE_UPDATE_LAYOUT_ONLY; + requestLayout(); } /** 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 d3052bcd62b41..c085d8092a1ff 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java @@ -24,6 +24,7 @@ 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; @@ -237,6 +238,13 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks mActionButtonTranslationZ = mActionButtonView.getTranslationZ(); } + /** + * Update the task view when the configuration changes. + */ + void onConfigurationChanged() { + mHeaderView.onConfigurationChanged(); + } + @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); 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 7f05fd1b55e8c..ddea4d98ae0ea 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -250,25 +250,7 @@ public class TaskViewHeader extends FrameLayout mFocusTimerIndicatorStub = (ViewStub) findViewById(R.id.focus_timer_indicator_stub); mAppOverlayViewStub = (ViewStub) findViewById(R.id.app_overlay_stub); - // Update the dimensions of everything in the header. We do this because we need to use - // resources for the display, and not the current configuration. - Resources res = getResources(); - mHeaderBarHeight = TaskStackLayoutAlgorithm.getDimensionForDevice(res, - R.dimen.recents_task_view_header_height, - R.dimen.recents_task_view_header_height, - R.dimen.recents_task_view_header_height, - R.dimen.recents_task_view_header_height_tablet_land, - R.dimen.recents_task_view_header_height, - R.dimen.recents_task_view_header_height_tablet_land); - mHeaderButtonPadding = TaskStackLayoutAlgorithm.getDimensionForDevice(res, - R.dimen.recents_task_view_header_button_padding, - R.dimen.recents_task_view_header_button_padding, - R.dimen.recents_task_view_header_button_padding, - R.dimen.recents_task_view_header_button_padding_tablet_land, - R.dimen.recents_task_view_header_button_padding, - R.dimen.recents_task_view_header_button_padding_tablet_land); - updateLayoutParams(mIconView, findViewById(R.id.title_container), mMoveTaskButton, - mDismissButton); + onConfigurationChanged(); } /** @@ -302,6 +284,34 @@ public class TaskViewHeader extends FrameLayout mHeaderButtonPadding); } + /** + * Update the header view when the configuration changes. + */ + void onConfigurationChanged() { + // Update the dimensions of everything in the header. We do this because we need to use + // resources for the display, and not the current configuration. + Resources res = getResources(); + mHeaderBarHeight = TaskStackLayoutAlgorithm.getDimensionForDevice(res, + R.dimen.recents_task_view_header_height, + R.dimen.recents_task_view_header_height, + R.dimen.recents_task_view_header_height, + R.dimen.recents_task_view_header_height_tablet_land, + R.dimen.recents_task_view_header_height, + R.dimen.recents_task_view_header_height_tablet_land); + mHeaderButtonPadding = TaskStackLayoutAlgorithm.getDimensionForDevice(res, + R.dimen.recents_task_view_header_button_padding, + R.dimen.recents_task_view_header_button_padding, + R.dimen.recents_task_view_header_button_padding, + R.dimen.recents_task_view_header_button_padding_tablet_land, + R.dimen.recents_task_view_header_button_padding, + R.dimen.recents_task_view_header_button_padding_tablet_land); + updateLayoutParams(mIconView, findViewById(R.id.title_container), mMoveTaskButton, + mDismissButton); + if (mAppOverlayView != null) { + updateLayoutParams(mAppIconView, mAppTitleView, null, mAppInfoView); + } + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom);