From dfde4d96ea740e35dfc4e1b32422b45a8c49e39e Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Fri, 19 Mar 2021 14:47:03 +0000 Subject: [PATCH] Focus running task in overview grid - calculateTaskSize now returns the Rect for focused task - Introduced calculateGridTaskSize for non-focused task, and translate non-focused tasks to fit the grid - As Task Rect is now vertically centered, removed ClearAllButton's grid vertical translation - When ClearAllButton is not shown (e.g. quickswitch), make sure ClearAllButton's scroll won't be used when page snapping. This happens when page scrolls are translated so they're negative. - Added back ActionsView when task is focused below the TaskView, which become invisible as you scroll - In Modal state, move the ActionsView down so it won't cover the TaskView Bug: 175939487 Test: manual Change-Id: Idfa94a51f856418adc0503cf04211dcb4b1814fe --- .../res/layout/overview_actions_container.xml | 5 +- .../res/layout/overview_actions_container.xml | 5 +- quickstep/res/values/dimens.xml | 1 + .../RecentsViewStateController.java | 7 +- .../states/OverviewModalTaskState.java | 12 +- .../uioverrides/states/OverviewState.java | 3 +- .../quickstep/BaseActivityInterface.java | 35 +++- .../FallbackRecentsStateController.java | 4 +- .../fallback/FallbackRecentsView.java | 2 +- .../quickstep/fallback/RecentsState.java | 4 +- .../quickstep/views/ClearAllButton.java | 40 ++-- .../quickstep/views/LauncherRecentsView.java | 34 +++- .../quickstep/views/OverviewActionsView.java | 35 +++- .../android/quickstep/views/RecentsView.java | 185 +++++++++++++----- .../com/android/quickstep/views/TaskView.java | 108 ++++++---- res/layout/overview_actions_container.xml | 2 + 16 files changed, 353 insertions(+), 129 deletions(-) diff --git a/go/quickstep/overview_ui_overrides/res/layout/overview_actions_container.xml b/go/quickstep/overview_ui_overrides/res/layout/overview_actions_container.xml index e6af84868e..866eac6e51 100644 --- a/go/quickstep/overview_ui_overrides/res/layout/overview_actions_container.xml +++ b/go/quickstep/overview_ui_overrides/res/layout/overview_actions_container.xml @@ -14,11 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. --> + + android:layout_height="wrap_content"> + + android:layout_height="wrap_content"> 90dp 54dp 42dp + 130dp 110dp 16dp diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index e1456b17ad..6929b5dc9c 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -103,12 +103,11 @@ public final class RecentsViewStateController extends private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config, LauncherState state) { - float clearAllButtonAlpha = (state.getVisibleElements(mLauncher) & CLEAR_ALL_BUTTON) != 0 - ? 1 : 0; + float clearAllButtonAlpha = state.areElementsVisible(mLauncher, CLEAR_ALL_BUTTON) ? 1 : 0; propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA, clearAllButtonAlpha, LINEAR); - float overviewButtonAlpha = (state.getVisibleElements(mLauncher) & OVERVIEW_ACTIONS) != 0 - ? 1 : 0; + float overviewButtonAlpha = state.areElementsVisible(mLauncher, OVERVIEW_ACTIONS) + && mRecentsView.shouldShowOverviewActionsForState(state) ? 1 : 0; propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(), MultiValueAlpha.VALUE, overviewButtonAlpha, config.getInterpolator( ANIM_OVERVIEW_ACTIONS_FADE, LINEAR)); diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java index bdba482c71..6f084a1f97 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java @@ -18,6 +18,7 @@ package com.android.launcher3.uioverrides.states; import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW; import android.content.Context; +import android.graphics.Point; import android.graphics.Rect; import com.android.launcher3.BaseDraggingActivity; @@ -70,13 +71,12 @@ public class OverviewModalTaskState extends OverviewState { } public static float[] getOverviewScaleAndOffsetForModalState(BaseDraggingActivity activity) { - Rect out = new Rect(); - activity.getOverviewPanel().getTaskSize(out); - int taskHeight = out.height(); - activity.getOverviewPanel().getModalTaskSize(out); - int newHeight = out.height(); + Point taskSize = activity.getOverviewPanel().getSelectedTaskSize(); + Rect modalTaskSize = new Rect(); + activity.getOverviewPanel().getModalTaskSize(modalTaskSize); - float scale = (float) newHeight / taskHeight; + float scale = Math.min((float) modalTaskSize.height() / taskSize.y, + (float) modalTaskSize.width() / taskSize.x); return new float[] {scale, NO_OFFSET}; } diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java index 43e70a3923..32bf3155bd 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java @@ -99,8 +99,7 @@ public class OverviewState extends LauncherState { @Override public int getVisibleElements(Launcher launcher) { - return displayOverviewTasksAsGrid(launcher.getDeviceProfile()) ? CLEAR_ALL_BUTTON - : CLEAR_ALL_BUTTON | OVERVIEW_ACTIONS; + return CLEAR_ALL_BUTTON | OVERVIEW_ACTIONS; } @Override diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index 0415009faf..3afffc1dad 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -206,18 +206,17 @@ public abstract class BaseActivityInterface +public class FallbackRecentsView extends RecentsView implements StateListener { private RunningTaskInfo mHomeTaskInfo; diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsState.java b/quickstep/src/com/android/quickstep/fallback/RecentsState.java index a9856d2dd8..bbe279e2f1 100644 --- a/quickstep/src/com/android/quickstep/fallback/RecentsState.java +++ b/quickstep/src/com/android/quickstep/fallback/RecentsState.java @@ -99,8 +99,8 @@ public class RecentsState implements BaseState { /** * For this state, whether overview actions should be shown. */ - public boolean hasOverviewActions(RecentsActivity activity) { - return hasFlag(FLAG_OVERVIEW_ACTIONS) && !showAsGrid(activity.getDeviceProfile()); + public boolean hasOverviewActions() { + return hasFlag(FLAG_OVERVIEW_ACTIONS); } public float[] getOverviewScaleAndOffset(RecentsActivity activity) { diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java index ff78995a1c..d616f7c7a5 100644 --- a/quickstep/src/com/android/quickstep/views/ClearAllButton.java +++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java @@ -45,12 +45,13 @@ public class ClearAllButton extends Button implements PageCallbacks { private float mScrollAlpha = 1; private float mContentAlpha = 1; private float mVisibilityAlpha = 1; + private float mFullscreenProgress = 1; private float mGridProgress = 1; private boolean mIsRtl; private float mNormalTranslationPrimary; + private float mFullscreenTranslationPrimary; private float mGridTranslationPrimary; - private float mGridTranslationSecondary; private float mGridScrollOffset; private float mScrollOffsetPrimary; @@ -130,13 +131,13 @@ public class ClearAllButton extends Button implements PageCallbacks { setClickable(Math.min(alpha, 1) == 1); } - public void setGridTranslationPrimary(float gridTranslationPrimary) { - mGridTranslationPrimary = gridTranslationPrimary; + public void setFullscreenTranslationPrimary(float fullscreenTranslationPrimary) { + mFullscreenTranslationPrimary = fullscreenTranslationPrimary; applyPrimaryTranslation(); } - public void setGridTranslationSecondary(float gridTranslationSecondary) { - mGridTranslationSecondary = gridTranslationSecondary; + public void setGridTranslationPrimary(float gridTranslationPrimary) { + mGridTranslationPrimary = gridTranslationPrimary; applyPrimaryTranslation(); } @@ -148,8 +149,11 @@ public class ClearAllButton extends Button implements PageCallbacks { mScrollOffsetPrimary = scrollOffsetPrimary; } - public float getScrollAdjustment(boolean gridEnabled) { + public float getScrollAdjustment(boolean fullscreenEnabled, boolean gridEnabled) { float scrollAdjustment = 0; + if (fullscreenEnabled) { + scrollAdjustment += mFullscreenTranslationPrimary; + } if (gridEnabled) { scrollAdjustment += mGridTranslationPrimary + mGridScrollOffset; } @@ -157,8 +161,18 @@ public class ClearAllButton extends Button implements PageCallbacks { return scrollAdjustment; } - public float getOffsetAdjustment(boolean gridEnabled) { - return getScrollAdjustment(gridEnabled); + public float getOffsetAdjustment(boolean fullscreenEnabled, boolean gridEnabled) { + return getScrollAdjustment(fullscreenEnabled, gridEnabled); + } + + /** + * Adjust translation when this TaskView is about to be shown fullscreen. + * + * @param progress: 0 = no translation; 1 = translate according to TaskVIew translations. + */ + public void setFullscreenProgress(float progress) { + mFullscreenProgress = progress; + applyPrimaryTranslation(); } /** @@ -180,7 +194,8 @@ public class ClearAllButton extends Button implements PageCallbacks { PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler(); orientationHandler.getPrimaryViewTranslate().set(this, orientationHandler.getPrimaryValue(0f, getOriginalTranslationY()) - + mNormalTranslationPrimary + getGridTrans(mGridTranslationPrimary)); + + mNormalTranslationPrimary + getFullscreenTrans( + mFullscreenTranslationPrimary) + getGridTrans(mGridTranslationPrimary)); } private void applySecondaryTranslation() { @@ -191,8 +206,11 @@ public class ClearAllButton extends Button implements PageCallbacks { PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler(); orientationHandler.getSecondaryViewTranslate().set(this, - orientationHandler.getSecondaryValue(0f, getOriginalTranslationY()) - + getGridTrans(mGridTranslationSecondary)); + orientationHandler.getSecondaryValue(0f, getOriginalTranslationY())); + } + + private float getFullscreenTrans(float endTranslation) { + return mFullscreenProgress > 0 ? endTranslation : 0; } private float getGridTrans(float endTranslation) { diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index a0af68a9bf..896d1ae58d 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -19,11 +19,13 @@ import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK; +import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT; import static com.android.launcher3.LauncherState.SPRING_LOADED; import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE; import android.annotation.TargetApi; import android.content.Context; +import android.content.res.Configuration; import android.os.Build; import android.util.AttributeSet; import android.view.MotionEvent; @@ -35,6 +37,7 @@ import com.android.launcher3.LauncherState; import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.statemanager.StateManager.StateListener; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; +import com.android.launcher3.util.SplitConfigurationOptions; import com.android.quickstep.LauncherActivityInterface; import com.android.quickstep.util.OverviewToHomeAnim; import com.android.systemui.plugins.PluginListener; @@ -44,7 +47,7 @@ import com.android.systemui.plugins.RecentsExtraCard; * {@link RecentsView} used in Launcher activity */ @TargetApi(Build.VERSION_CODES.O) -public class LauncherRecentsView extends RecentsView +public class LauncherRecentsView extends RecentsView implements StateListener { private RecentsExtraCard mRecentsExtraCardPlugin; @@ -234,4 +237,33 @@ public class LauncherRecentsView extends RecentsView } } } + + @Override + protected void onDismissAnimationEnds() { + super.onDismissAnimationEnds(); + if (mActivity.isInState(OVERVIEW_SPLIT_SELECT)) { + // We want to keep the tasks translations in this temporary state + // after resetting the rest above + setTaskViewsResistanceTranslation(mTaskViewsSecondaryTranslation); + setTaskViewsPrimaryTranslation(mTaskViewsPrimaryTranslation); + } + } + + @Override + public void initiateSplitSelect(TaskView taskView, + SplitConfigurationOptions.SplitPositionOption splitPositionOption) { + super.initiateSplitSelect(taskView, splitPositionOption); + mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT); + } + + @Override + protected void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + // If overview is in modal state when rotate, reset it to overview state without running + // animation. + if (mActivity.isInState(OVERVIEW_MODAL_TASK)) { + mActivity.getStateManager().goToState(LauncherState.OVERVIEW, false); + resetModalVisuals(); + } + } } diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java index 6fcd54cf62..9adeea42f0 100644 --- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java +++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java @@ -16,6 +16,7 @@ package com.android.quickstep.views; +import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_SHARE; import android.content.Context; @@ -32,6 +33,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; import com.android.launcher3.R; +import com.android.launcher3.Utilities; import com.android.launcher3.util.MultiValueAlpha; import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.quickstep.SysUINavigationMode; @@ -76,6 +78,7 @@ public class OverviewActionsView extends FrameLayo private static final int INDEX_VISIBILITY_ALPHA = 1; private static final int INDEX_FULLSCREEN_ALPHA = 2; private static final int INDEX_HIDDEN_FLAGS_ALPHA = 3; + private static final int INDEX_SCROLL_ALPHA = 4; private final MultiValueAlpha mMultiValueAlpha; @@ -87,6 +90,9 @@ public class OverviewActionsView extends FrameLayo protected T mCallbacks; + private float mModalness; + private float mModalTransformY; + public OverviewActionsView(Context context) { this(context, null); } @@ -97,7 +103,7 @@ public class OverviewActionsView extends FrameLayo public OverviewActionsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr, 0); - mMultiValueAlpha = new MultiValueAlpha(this, 4); + mMultiValueAlpha = new MultiValueAlpha(this, 5); mMultiValueAlpha.setUpdateVisibility(true); } @@ -189,6 +195,10 @@ public class OverviewActionsView extends FrameLayo return mMultiValueAlpha.getProperty(INDEX_FULLSCREEN_ALPHA); } + public AlphaProperty getScrollAlpha() { + return mMultiValueAlpha.getProperty(INDEX_SCROLL_ALPHA); + } + private void updateHorizontalPadding() { setPadding(mInsets.left, 0, mInsets.right, 0); } @@ -224,4 +234,27 @@ public class OverviewActionsView extends FrameLayo bottomMargin += mInsets.bottom; return bottomMargin; } + + /** + * The current task is fully modal (modalness = 1) when it is shown on its own in a modal + * way. Modalness 0 means the task is shown in context with all the other tasks. + */ + public void setTaskModalness(float modalness) { + mModalness = modalness; + applyTranslationY(); + } + + public void setModalTransformY(float modalTransformY) { + mModalTransformY = modalTransformY; + applyTranslationY(); + } + + private void applyTranslationY() { + setTranslationY(getModalTrans(mModalTransformY)); + } + + private float getModalTrans(float endTranslation) { + float progress = ACCEL_DEACCEL.getInterpolation(mModalness); + return Utilities.mapRange(progress, 0, endTranslation); + } } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index ad266ce542..b688f1ec4b 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -25,8 +25,6 @@ import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARA import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS; import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA; import static com.android.launcher3.LauncherState.BACKGROUND_APP; -import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK; -import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT; import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION; import static com.android.launcher3.Utilities.EDGE_NAV_BAR; import static com.android.launcher3.Utilities.mapToRange; @@ -81,6 +79,7 @@ import android.util.AttributeSet; import android.util.FloatProperty; import android.util.Log; import android.util.SparseBooleanArray; +import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; import android.view.LayoutInflater; @@ -91,6 +90,7 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.Interpolator; +import android.widget.FrameLayout; import android.widget.ListView; import androidx.annotation.Nullable; @@ -100,7 +100,6 @@ import com.android.launcher3.BaseActivity.MultiWindowModeChangedListener; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.LauncherState; import com.android.launcher3.PagedView; import com.android.launcher3.R; import com.android.launcher3.Utilities; @@ -111,6 +110,7 @@ import com.android.launcher3.anim.SpringProperty; import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.statehandlers.DepthController; +import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.PagedOrientationHandler; @@ -161,8 +161,9 @@ import java.util.function.Consumer; * A list of recent tasks. */ @TargetApi(Build.VERSION_CODES.R) -public abstract class RecentsView extends PagedView implements - Insettable, TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback, +public abstract class RecentsView, + STATE_TYPE extends BaseState> extends PagedView implements Insettable, + TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback, InvariantDeviceProfile.OnIDPChangeListener, TaskVisualsChangeListener, SplitScreenBounds.OnChangeListener { @@ -295,7 +296,7 @@ public abstract class RecentsView extends PagedView }; protected final RecentsOrientedState mOrientationState; - protected final BaseActivityInterface mSizeStrategy; + protected final BaseActivityInterface mSizeStrategy; protected RecentsAnimationController mRecentsAnimationController; protected SurfaceTransactionApplier mSyncTransactionApplier; protected int mTaskWidth; @@ -304,6 +305,7 @@ public abstract class RecentsView extends PagedView protected final TaskViewSimulator mLiveTileTaskViewSimulator; protected final Rect mLastComputedTaskSize = new Rect(); protected final Rect mLastComputedGridSize = new Rect(); + protected final Rect mLastComputedGridTaskSize = new Rect(); // How much a task that is directly offscreen will be pushed out due to RecentsView scale/pivot. protected Float mLastComputedTaskPushOutDistance = null; protected boolean mEnableDrawingLiveTile = false; @@ -317,10 +319,11 @@ public abstract class RecentsView extends PagedView // The threshold at which we update the SystemUI flags when animating from the task into the app public static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.85f; - protected final T mActivity; + protected final ACTIVITY_TYPE mActivity; private final float mFastFlingVelocity; private final RecentsModel mModel; private final int mRowSpacing; + private final int mGridSideMargin; private final ClearAllButton mClearAllButton; private final Rect mClearAllButtonDeadZoneRect = new Rect(); private final Rect mTaskViewDeadZoneRect = new Rect(); @@ -347,8 +350,8 @@ public abstract class RecentsView extends PagedView private boolean mOverviewFullscreenEnabled; private float mAdjacentPageOffset = 0; - private float mTaskViewsSecondaryTranslation = 0; - private float mTaskViewsPrimaryTranslation = 0; + protected float mTaskViewsSecondaryTranslation = 0; + protected float mTaskViewsPrimaryTranslation = 0; // Progress from 0 to 1 where 0 is a carousel and 1 is a 2 row grid. private float mGridProgress = 0; @@ -436,6 +439,8 @@ public abstract class RecentsView extends PagedView protected int mRunningTaskId = -1; protected boolean mRunningTaskTileHidden; private Task mTmpRunningTask; + protected int mFocusedTaskId = -1; + private float mFocusedTaskRatio; private boolean mRunningTaskIconScaledDown = false; @@ -541,6 +546,7 @@ public abstract class RecentsView extends PagedView mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources()); setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR); mRowSpacing = getResources().getDimensionPixelSize(R.dimen.overview_grid_row_spacing); + mGridSideMargin = getResources().getDimensionPixelSize(R.dimen.overview_grid_side_margin); mSquaredTouchSlop = squaredTouchSlop(context); mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents); @@ -645,7 +651,6 @@ public abstract class RecentsView extends PagedView mActionsView = actionsView; mActionsView.updateHiddenFlags(HIDDEN_NO_TASKS, getTaskViewCount() == 0); mSplitPlaceholderView = splitPlaceholderView; - } public SplitPlaceholderView getSplitPlaceholder() { @@ -1119,6 +1124,7 @@ public abstract class RecentsView extends PagedView for (int i = 0; i < taskCount; i++) { getTaskViewAt(i).setFullscreenProgress(mFullscreenProgress); } + mClearAllButton.setFullscreenProgress(fullscreenProgress); // Fade out the actions view quickly (0.1 range) mActionsView.getFullscreenAlpha().setValue( @@ -1158,9 +1164,31 @@ public abstract class RecentsView extends PagedView mSizeStrategy.calculateGridSize(mActivity, mActivity.getDeviceProfile(), mLastComputedGridSize); + mSizeStrategy.calculateGridTaskSize(mActivity, mActivity.getDeviceProfile(), + mLastComputedGridTaskSize, mOrientationHandler); // Force TaskView to update size from thumbnail updateTaskSize(); + + // Update ActionsView position + FrameLayout.LayoutParams layoutParams = + (FrameLayout.LayoutParams) mActionsView.getLayoutParams(); + if (dp.isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) { + layoutParams.gravity = Gravity.BOTTOM; + layoutParams.bottomMargin = + dp.heightPx - mInsets.bottom - mLastComputedGridSize.bottom; + layoutParams.leftMargin = mLastComputedTaskSize.left; + layoutParams.rightMargin = dp.widthPx - mLastComputedTaskSize.right; + // When in modal state, remove bottom margin to avoid covering content. + mActionsView.setModalTransformY(layoutParams.bottomMargin); + } else { + layoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM; + layoutParams.bottomMargin = 0; + layoutParams.leftMargin = 0; + layoutParams.rightMargin = 0; + mActionsView.setModalTransformY(0); + } + mActionsView.setLayoutParams(layoutParams); } /** @@ -1201,6 +1229,8 @@ public abstract class RecentsView extends PagedView getTaskViewAt(i).setFullscreenTranslationX( fullscreenTranslations[i] - fullscreenTranslations[firstNonHomeTaskIndex]); } + mClearAllButton.setFullscreenTranslationPrimary( + accumulatedTranslationX - fullscreenTranslations[firstNonHomeTaskIndex]); // Align ClearAllButton to the left (RTL) or right (non-RTL), which is different from other // TaskViews. @@ -1216,11 +1246,36 @@ public abstract class RecentsView extends PagedView mLastComputedTaskSize.set(outRect); } + /** + * Returns the size of task selected to enter modal state. + */ + public Point getSelectedTaskSize() { + mSizeStrategy.calculateTaskSize(mActivity, mActivity.getDeviceProfile(), mTempRect, + mOrientationHandler); + int taskWidth = mTempRect.width(); + int taskHeight = mTempRect.height(); + if (mRunningTaskId != -1) { + int boxLength = Math.max(taskWidth, taskHeight); + if (mFocusedTaskRatio > 1) { + taskWidth = boxLength; + taskHeight = (int) (boxLength / mFocusedTaskRatio); + } else { + taskWidth = (int) (boxLength * mFocusedTaskRatio); + taskHeight = boxLength; + } + } + return new Point(taskWidth, taskHeight); + } + /** Gets the last computed task size */ public Rect getLastComputedTaskSize() { return mLastComputedTaskSize; } + public Rect getLastComputedGridTaskSize() { + return mLastComputedGridTaskSize; + } + /** Gets the task size for modal state. */ public void getModalTaskSize(Rect outRect) { mSizeStrategy.calculateModalTaskSize(mActivity, mActivity.getDeviceProfile(), outRect); @@ -1239,6 +1294,15 @@ public abstract class RecentsView extends PagedView // After scrolling, update the visible task's data loadVisibleTaskData(TaskView.FLAG_UPDATE_ALL); + + // After scrolling, update ActionsView's visibility. + TaskView focusedTaskView = getFocusedTaskView(); + if (focusedTaskView != null) { + float scrollDiff = Math.abs(getScrollForPage(indexOfChild(focusedTaskView)) + - mOrientationHandler.getPrimaryScroll(this)); + float delta = (mGridSideMargin - scrollDiff) / (float) mGridSideMargin; + mActionsView.getScrollAlpha().setValue(Utilities.boundToRange(delta, 0, 1)); + } } // Update the high res thumbnail loader state @@ -1403,6 +1467,7 @@ public abstract class RecentsView extends PagedView setCurrentTask(-1); mIgnoreResetTaskId = -1; mTaskListChangeId = -1; + mFocusedTaskId = -1; mRecentsAnimationController = null; mLiveTileParams.setTargetSet(null); @@ -1429,6 +1494,17 @@ public abstract class RecentsView extends PagedView return getTaskIndexForId(mRunningTaskId); } + public @Nullable TaskView getFocusedTaskView() { + return getTaskView(mFocusedTaskId); + } + + /** + * Returns the width to height ratio of the focused {@link TaskView}. + */ + public float getFocusedTaskRatio() { + return mFocusedTaskRatio; + } + /** * Get the index of the task view whose id matches {@param taskId}. * @return -1 if there is no task view for the task id, else the index of the task view. @@ -1520,6 +1596,11 @@ public abstract class RecentsView extends PagedView */ public void onGestureEndTargetCalculated(GestureState.GestureEndTarget endTarget) { mCurrentGestureEndTarget = endTarget; + if (showAsGrid()) { + mFocusedTaskId = mRunningTaskId; + mFocusedTaskRatio = + mLastComputedTaskSize.width() / (float) mLastComputedTaskSize.height(); + } } /** @@ -1540,8 +1621,7 @@ public abstract class RecentsView extends PagedView setRunningTaskHidden(false); animateUpRunningTaskIconScale(); - // TODO: This should be tied to whether there is a focus app on overview. - if (!showAsGrid()) { + if (!showAsGrid() || getFocusedTaskView() != null) { animateActionsViewIn(); } @@ -1661,6 +1741,13 @@ public abstract class RecentsView extends PagedView anim.start(); } + private void animateActionsViewOut() { + ObjectAnimator anim = ObjectAnimator.ofFloat( + mActionsView.getVisibilityAlpha(), MultiValueAlpha.VALUE, 1, 0); + anim.setDuration(TaskView.SCALE_ICON_DURATION); + anim.start(); + } + public void animateUpRunningTaskIconScale() { animateUpRunningTaskIconScale(0); } @@ -1686,8 +1773,12 @@ public abstract class RecentsView extends PagedView return; } - final int boxLength = Math.max(mTaskWidth, mTaskHeight); + final int boxLength = Math.max(mLastComputedGridTaskSize.width(), + mLastComputedGridTaskSize.height()); int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx; + float heightOffset = (boxLength + taskTopMargin) + mRowSpacing; + float taskGridVerticalDiff = mLastComputedGridTaskSize.top - mLastComputedTaskSize.top; + int topRowWidth = 0; int bottomRowWidth = 0; float topAccumulatedTranslationX = 0; @@ -1710,15 +1801,23 @@ public abstract class RecentsView extends PagedView } // Evenly distribute tasks between rows unless rearranging due to task dismissal, in - // which case keep tasks in their respective rows. - if ((!isTaskDismissal && topRowWidth <= bottomRowWidth) || (isTaskDismissal && mTopIdSet - .contains(taskView.getTask().key.id))) { + // which case keep tasks in their respective rows. For the running task, don't join + // the grid. + if (taskView.isRunningTask()) { + topRowWidth += taskView.getLayoutParams().width + mPageSpacing; + bottomRowWidth += taskView.getLayoutParams().width + mPageSpacing; + + // Center view vertically in case it's from different orientation. + taskView.setGridTranslationY((mLastComputedTaskSize.height() + taskTopMargin + - taskView.getLayoutParams().height) / 2f); + } else if ((!isTaskDismissal && topRowWidth <= bottomRowWidth) || (isTaskDismissal + && mTopIdSet.contains(taskView.getTask().key.id))) { gridTranslations[i] += topAccumulatedTranslationX; topRowWidth += taskView.getLayoutParams().width + mPageSpacing; topSet.add(i); mTopIdSet.add(taskView.getTask().key.id); - taskView.setGridTranslationY(0); + taskView.setGridTranslationY(taskGridVerticalDiff); // Move horizontally into empty space. float widthOffset = 0; @@ -1735,8 +1834,7 @@ public abstract class RecentsView extends PagedView bottomSet.add(i); // Move into bottom row. - float heightOffset = (boxLength + taskTopMargin) + mRowSpacing; - taskView.setGridTranslationY(heightOffset); + taskView.setGridTranslationY(heightOffset + taskGridVerticalDiff); // Move horizontally into empty space. float widthOffset = 0; @@ -1794,8 +1892,6 @@ public abstract class RecentsView extends PagedView mClearAllButton.setGridTranslationPrimary( clearAllTotalTranslationX - gridTranslations[firstNonHomeTaskIndex]); - mClearAllButton.setGridTranslationSecondary( - boxLength - mTaskHeight / 2f + mRowSpacing / 2f); mClearAllButton.setGridScrollOffset( mIsRtl ? mLastComputedTaskSize.left - mLastComputedGridSize.left : mLastComputedTaskSize.right - mLastComputedGridSize.right); @@ -2072,24 +2168,25 @@ public abstract class RecentsView extends PagedView snapToPageImmediately(pageToSnapTo); // Grid got messed up, reapply. updateGridProperties(true); + if (showAsGrid() && getFocusedTaskView() == null) { + animateActionsViewOut(); + } } // Update the layout synchronously so that the position of next view is // immediately available. onLayout(false /* changed */, getLeft(), getTop(), getRight(), getBottom()); } resetTaskVisuals(); - if (mActivity.isInState(OVERVIEW_SPLIT_SELECT)) { - // We want to keep the tasks translations in this temporary state - // after resetting the rest above - setTaskViewsResistanceTranslation(mTaskViewsSecondaryTranslation); - setTaskViewsPrimaryTranslation(mTaskViewsPrimaryTranslation); - } + onDismissAnimationEnds(); mPendingAnimation = null; } }); return anim; } + protected void onDismissAnimationEnds() { + } + public PendingAnimation createAllTasksDismissAnimation(long duration) { if (FeatureFlags.IS_STUDIO_BUILD && mPendingAnimation != null) { throw new IllegalStateException("Another pending animation is still running"); @@ -2257,13 +2354,6 @@ public abstract class RecentsView extends PagedView if (mOrientationState.setRecentsRotation(rotation)) { updateOrientationHandler(); } - - // If overview is in modal state when rotate, reset it to overview state without running - // animation. - if (mActivity.isInState(OVERVIEW_MODAL_TASK)) { - mActivity.getStateManager().goToState(LauncherState.OVERVIEW, false); - resetModalVisuals(); - } } public void setLayoutRotation(int touchRotation, int displayRotation) { @@ -2475,7 +2565,7 @@ public abstract class RecentsView extends PagedView return distanceToOffscreen * offsetProgress; } - private void setTaskViewsResistanceTranslation(float translation) { + protected void setTaskViewsResistanceTranslation(float translation) { mTaskViewsSecondaryTranslation = translation; for (int i = 0; i < getTaskViewCount(); i++) { TaskView task = getTaskViewAt(i); @@ -2484,7 +2574,7 @@ public abstract class RecentsView extends PagedView mLiveTileTaskViewSimulator.recentsViewSecondaryTranslation.value = translation; } - private void setTaskViewsPrimaryTranslation(float translation) { + protected void setTaskViewsPrimaryTranslation(float translation) { mTaskViewsPrimaryTranslation = translation; for (int i = 0; i < getTaskViewCount(); i++) { TaskView task = getTaskViewAt(i); @@ -2515,7 +2605,6 @@ public abstract class RecentsView extends PagedView mSplitPlaceholderView.getSplitController().setInitialTaskSelect(taskView, splitPositionOption); mSplitHiddenTaskViewIndex = indexOfChild(taskView); - mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT); } public PendingAnimation createSplitSelectInitAnimation() { @@ -2943,10 +3032,7 @@ public abstract class RecentsView extends PagedView * Returns page scroll of the left most child. */ public int getLeftMostChildScroll() { - if (mIsRtl) { - return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1); - } - return getScrollForPage(mTaskViewStartIndex); + return getScrollForPage(mIsRtl ? indexOfChild(mClearAllButton) : mTaskViewStartIndex); } @Override @@ -2957,10 +3043,7 @@ public abstract class RecentsView extends PagedView // so use the rightmost task as the min scroll. return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1))); } - if (mIsRtl) { - return getScrollForPage(mTaskViewStartIndex); - } - return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1); + return getScrollForPage(mIsRtl ? mTaskViewStartIndex : indexOfChild(mClearAllButton)); } return super.computeMaxScroll(); } @@ -2979,7 +3062,8 @@ public abstract class RecentsView extends PagedView scrollDiff = ((TaskView) child).getScrollAdjustment(mOverviewFullscreenEnabled, showAsGrid()); } else if (child instanceof ClearAllButton) { - scrollDiff = ((ClearAllButton) child).getScrollAdjustment(showAsGrid()); + scrollDiff = ((ClearAllButton) child).getScrollAdjustment( + mOverviewFullscreenEnabled, showAsGrid()); } if (scrollDiff != 0) { @@ -2998,7 +3082,8 @@ public abstract class RecentsView extends PagedView childOffset += ((TaskView) child).getOffsetAdjustment(mOverviewFullscreenEnabled, showAsGrid()); } else if (child instanceof ClearAllButton) { - childOffset += ((ClearAllButton) child).getOffsetAdjustment(showAsGrid()); + childOffset += ((ClearAllButton) child).getOffsetAdjustment(mOverviewFullscreenEnabled, + showAsGrid()); } return childOffset; } @@ -3174,6 +3259,7 @@ public abstract class RecentsView extends PagedView boolean inPlaceLandscape = !mOrientationState.canRecentsActivityRotate() && mOrientationState.getTouchRotation() != ROTATION_0; mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, modalness < 1 && inPlaceLandscape); + mActionsView.setTaskModalness(modalness); } @Nullable @@ -3208,6 +3294,11 @@ public abstract class RecentsView extends PagedView mCurrentGestureEndTarget).displayOverviewTasksAsGrid(mActivity.getDeviceProfile())); } + public boolean shouldShowOverviewActionsForState(STATE_TYPE state) { + return !state.displayOverviewTasksAsGrid(mActivity.getDeviceProfile()) + || getFocusedTaskView() != null; + } + /** * Used to register callbacks for when our empty message state changes. * diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 21b11644d2..745e328ab3 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -987,7 +987,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { return scrollAdjustment; } - public float getOffsetAdjustment(boolean fullscreenEnabled,boolean gridEnabled) { + public float getOffsetAdjustment(boolean fullscreenEnabled, boolean gridEnabled) { return getScrollAdjustment(fullscreenEnabled, gridEnabled); } @@ -1213,62 +1213,77 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { */ void updateTaskSize() { ViewGroup.LayoutParams params = getLayoutParams(); + float fullscreenScale; + float boxTranslationY; + int expectedWidth; + int expectedHeight; if (mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) { final int thumbnailPadding = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx; + final Rect lastComputedTaskSize = getRecentsView().getLastComputedTaskSize(); + final int taskWidth = lastComputedTaskSize.width(); + final int taskHeight = lastComputedTaskSize.height(); - Rect lastComputedTaskSize = getRecentsView().getLastComputedTaskSize(); - int taskWidth = lastComputedTaskSize.width(); - int taskHeight = lastComputedTaskSize.height(); - - int expectedWidth; - int expectedHeight; - float thumbnailRatio = mTask != null ? mTask.getVisibleThumbnailRatio( - TaskView.CLIP_STATUS_AND_NAV_BARS) : 0f; - if (isRunningTask() || thumbnailRatio == 0f) { - expectedWidth = taskWidth; - expectedHeight = taskHeight + thumbnailPadding; + int boxWidth; + int boxHeight; + float thumbnailRatio; + boolean isFocusedTask = isFocusedTask(); + if (isFocusedTask || isRunningTask()) { + // Task will be focused and should use focused task size. Use runningTaskRatio + // that is associated with the original orientation of the focused task if possible. + boxWidth = taskWidth; + boxHeight = taskHeight; + thumbnailRatio = isFocusedTask ? getRecentsView().getFocusedTaskRatio() : 0; } else { - int boxLength = Math.max(taskWidth, taskHeight); - if (thumbnailRatio > 1) { - expectedWidth = boxLength; - expectedHeight = (int) (boxLength / thumbnailRatio) + thumbnailPadding; - } else { - expectedWidth = (int) (boxLength * thumbnailRatio); - expectedHeight = boxLength + thumbnailPadding; - } + // Otherwise task is in grid, and should use lastComputedGridTaskSize. + Rect lastComputedGridTaskSize = getRecentsView().getLastComputedGridTaskSize(); + boxWidth = lastComputedGridTaskSize.width(); + boxHeight = lastComputedGridTaskSize.height(); + thumbnailRatio = mTask != null ? mTask.getVisibleThumbnailRatio( + TaskView.CLIP_STATUS_AND_NAV_BARS) : 0f; + } + int boxLength = Math.max(boxWidth, boxHeight); + + // Bound width/height to the box size. + if (thumbnailRatio == 0f) { + expectedWidth = boxWidth; + expectedHeight = boxHeight + thumbnailPadding; + } else if (thumbnailRatio > 1) { + expectedWidth = boxLength; + expectedHeight = (int) (boxLength / thumbnailRatio) + thumbnailPadding; + } else { + expectedWidth = (int) (boxLength * thumbnailRatio); + expectedHeight = boxLength + thumbnailPadding; } - float heightDiff = (expectedHeight - thumbnailPadding - taskHeight) / 2.0f; - setBoxTranslationY(heightDiff); + // Scale to to fit task Rect. + fullscreenScale = taskWidth / (float) boxWidth; - float fullscreenScale = 1f; - if (expectedWidth > taskWidth) { - // In full screen, expectedWidth should not be larger than taskWidth. - fullscreenScale = taskWidth / (float) expectedWidth; - } else if (expectedHeight - thumbnailPadding > taskHeight) { - // In full screen, expectedHeight should not be larger than taskHeight. - fullscreenScale = taskHeight / (float) (expectedHeight - thumbnailPadding); + // In full screen, scale back TaskView to original size. + if (expectedWidth > boxWidth) { + fullscreenScale *= boxWidth / (float) expectedWidth; + } else if (expectedHeight - thumbnailPadding > boxHeight) { + fullscreenScale *= boxHeight / (float) (expectedHeight - thumbnailPadding); } - setFullscreenScale(fullscreenScale); - if (params.width != expectedWidth || params.height != expectedHeight) { - params.width = expectedWidth; - params.height = expectedHeight; - setLayoutParams(params); - } + // Align to top of task Rect. + boxTranslationY = (expectedHeight - thumbnailPadding - taskHeight) / 2.0f; } else { - setBoxTranslationY(0); - setFullscreenScale(1); - if (params.width != ViewGroup.LayoutParams.MATCH_PARENT) { - params.width = ViewGroup.LayoutParams.MATCH_PARENT; - params.height = ViewGroup.LayoutParams.MATCH_PARENT; - setLayoutParams(params); - } + fullscreenScale = 1f; + boxTranslationY = 0f; + expectedWidth = ViewGroup.LayoutParams.MATCH_PARENT; + expectedHeight = ViewGroup.LayoutParams.MATCH_PARENT; + } + + setFullscreenScale(fullscreenScale); + setBoxTranslationY(boxTranslationY); + if (params.width != expectedWidth || params.height != expectedHeight) { + params.width = expectedWidth; + params.height = expectedHeight; + setLayoutParams(params); } } - private float getFullscreenTrans(float endTranslation) { float progress = ACCEL_DEACCEL.getInterpolation(mFullscreenProgress); return Utilities.mapRange(progress, 0, endTranslation); @@ -1281,6 +1296,13 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { return this == getRecentsView().getRunningTaskView(); } + public boolean isFocusedTask() { + if (getRecentsView() == null) { + return false; + } + return this == getRecentsView().getFocusedTaskView(); + } + public void setShowScreenshot(boolean showScreenshot) { mShowScreenshot = showScreenshot; } diff --git a/res/layout/overview_actions_container.xml b/res/layout/overview_actions_container.xml index 5946bf67ec..f152c7c727 100644 --- a/res/layout/overview_actions_container.xml +++ b/res/layout/overview_actions_container.xml @@ -14,6 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. --> +