diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 87ca2b688a..e074b03c09 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -17,6 +17,7 @@ package com.android.launcher3.uioverrides; 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.quickstep.SysUINavigationMode.Mode.NO_BUTTON; import android.content.Intent; @@ -219,7 +220,12 @@ public class QuickstepLauncher extends BaseQuickstepLauncher { @Override protected boolean isRecentsInteractive() { - return mActivity.isInState(OVERVIEW); + return mActivity.isInState(OVERVIEW) || mActivity.isInState(OVERVIEW_MODAL_TASK); + } + + @Override + protected boolean isRecentsModal() { + return mActivity.isInState(OVERVIEW_MODAL_TASK); } @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index 2f55fda8f0..a1cc60ec71 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -19,6 +19,7 @@ import static com.android.launcher3.LauncherState.OVERVIEW_BUTTONS; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA; import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; +import static com.android.quickstep.views.RecentsView.TASK_MODALNESS; import android.annotation.TargetApi; import android.os.Build; @@ -87,6 +88,11 @@ public final class RecentsViewStateController extends MultiValueAlpha.VALUE, buttonAlpha, LINEAR); } + @Override + FloatProperty getTaskModalnessProperty() { + return TASK_MODALNESS; + } + @Override FloatProperty getContentAlphaProperty() { return CONTENT_ALPHA; diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java new file mode 100644 index 0000000000..b238200799 --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.uioverrides.states; + +import android.content.res.Resources; +import android.graphics.Rect; + +import com.android.launcher3.Launcher; +import com.android.launcher3.R; +import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; +import com.android.quickstep.views.RecentsView; + +/** + * An Overview state that shows the current task in a modal fashion. Modal state is where the + * current task is shown on its own without other tasks visible. + */ +public class OverviewModalTaskState extends OverviewState { + + private static final int STATE_FLAGS = + FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_DISABLE_ACCESSIBILITY; + + public OverviewModalTaskState(int id) { + super(id, ContainerType.OVERVIEW, STATE_FLAGS); + } + + @Override + public int getTransitionDuration(Launcher launcher) { + return 100; + } + + @Override + public int getVisibleElements(Launcher launcher) { + return OVERVIEW_BUTTONS; + } + + @Override + public float[] getOverviewScaleAndOffset(Launcher launcher) { + Resources res = launcher.getBaseContext().getResources(); + + Rect out = new Rect(); + launcher.getOverviewPanel().getTaskSize(out); + int taskHeight = out.height(); + + float topMargin = res.getDimension(R.dimen.task_thumbnail_top_margin); + float bottomMargin = res.getDimension(R.dimen.task_thumbnail_bottom_margin_with_actions); + float newHeight = taskHeight + topMargin + bottomMargin; + float scale = newHeight / taskHeight; + + return new float[] {scale, 0}; + } + + @Override + public float getOverviewModalness() { + return 1.0f; + } +} diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java index e44f59fd71..fad9ea5817 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/states/OverviewState.java @@ -259,4 +259,11 @@ public class OverviewState extends LauncherState { public static OverviewState newSwitchState(int id) { return new QuickSwitchState(id); } + + /** + * New Overview substate that represents the overview in modal mode (one task shown on its own) + */ + public static OverviewState newModalTaskState(int id) { + return new OverviewModalTaskState(id); + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java index 2b456ecec8..06a481b90d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java @@ -17,7 +17,6 @@ package com.android.launcher3.uioverrides.touchcontrollers; import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.LauncherState.NORMAL; -import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; import static com.android.launcher3.anim.Interpolators.DEACCEL_3; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; @@ -99,7 +98,7 @@ public class NavBarToHomeTouchController implements TouchController, if (!cameFromNavBar) { return false; } - if (mStartState == OVERVIEW || mStartState == ALL_APPS) { + if (mStartState.overviewUi || mStartState == ALL_APPS) { return true; } if (AbstractFloatingView.getTopOpenView(mLauncher) != null) { @@ -129,7 +128,7 @@ public class NavBarToHomeTouchController implements TouchController, private void initCurrentAnimation() { long accuracy = (long) (getShiftRange() * 2); final PendingAnimation builder = new PendingAnimation(accuracy); - if (mStartState == OVERVIEW) { + if (mStartState.overviewUi) { RecentsView recentsView = mLauncher.getOverviewPanel(); builder.setFloat(recentsView, ADJACENT_PAGE_OFFSET, -mPullbackDistance / recentsView.getPageOffsetScale(), PULLBACK_INTERPOLATOR); diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java index f6f892b44b..1f3b82cd98 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/TaskViewTouchController.java @@ -96,6 +96,9 @@ public abstract class TaskViewTouchController protected abstract boolean isRecentsInteractive(); + /** Is recents view showing a single task in a modal way. */ + protected abstract boolean isRecentsModal(); + protected void onUserControlledAnimationCreated(AnimatorPlaybackController animController) { } @@ -134,7 +137,7 @@ public abstract class TaskViewTouchController if (mRecentsView.isTaskViewVisible(view) && mActivity.getDragLayer() .isEventOverView(view, ev)) { // Disable swiping up and down if the task overlay is modal. - if (view.isTaskOverlayModal()) { + if (isRecentsModal()) { mTaskBeingDragged = null; break; } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java index 147f9330c7..b44d6df26e 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java @@ -130,13 +130,6 @@ public class TaskOverlayFactory implements ResourceBasedOverride { public void reset() { } - /** - * Whether the overlay is modal, which means only tapping is enabled, but no swiping. - */ - public boolean isOverlayModal() { - return false; - } - /** * Gets the task snapshot as it is displayed on the screen. * diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsTaskController.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsTaskController.java index a113604caa..d7458d2ad9 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsTaskController.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/RecentsTaskController.java @@ -28,4 +28,9 @@ public class RecentsTaskController extends TaskViewTouchController // Clean-up logic that occurs when recents is no longer in use/visible. reset(); } - setOverlayEnabled(finalState == OVERVIEW); + setOverlayEnabled(finalState == OVERVIEW || finalState == OVERVIEW_MODAL_TASK); setFreezeViewVisibility(false); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index 6041917f67..cd3abed042 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -70,7 +70,6 @@ import android.text.StaticLayout; import android.text.TextPaint; import android.util.AttributeSet; import android.util.FloatProperty; -import android.util.Log; import android.util.Property; import android.util.SparseBooleanArray; import android.view.HapticFeedbackConstants; @@ -173,13 +172,26 @@ public abstract class RecentsView extends PagedView impl } }; + public static final FloatProperty TASK_MODALNESS = + new FloatProperty("taskModalness") { + @Override + public void setValue(RecentsView recentsView, float v) { + recentsView.setTaskModalness(v); + } + + @Override + public Float get(RecentsView recentsView) { + return recentsView.mTaskModalness; + } + }; + public static final FloatProperty ADJACENT_PAGE_OFFSET = new FloatProperty("adjacentPageOffset") { @Override public void setValue(RecentsView recentsView, float v) { if (recentsView.mAdjacentPageOffset != v) { recentsView.mAdjacentPageOffset = v; - recentsView.updateAdjacentPageOffset(); + recentsView.updatePageOffsets(); } } @@ -327,6 +339,12 @@ public abstract class RecentsView extends PagedView impl protected float mContentAlpha = 1; @ViewDebug.ExportedProperty(category = "launcher") protected float mFullscreenProgress = 0; + /** + * How modal is the current task to be displayed, 1 means the task is fully modal and no other + * tasks are show. 0 means the task is displays in context in the list with other tasks. + */ + @ViewDebug.ExportedProperty(category = "launcher") + protected float mTaskModalness = 0; // Keeps track of task id whose visual state should not be reset private int mIgnoreResetTaskId = -1; @@ -647,7 +665,7 @@ public abstract class RecentsView extends PagedView impl @Override protected void determineScrollingStart(MotionEvent ev, float touchSlopScale) { // Enables swiping to the left or right only if the task overlay is not modal. - if (getCurrentPageTaskView() == null || !getCurrentPageTaskView().isTaskOverlayModal()) { + if (mTaskModalness == 0f) { super.determineScrollingStart(ev, touchSlopScale); } } @@ -735,25 +753,6 @@ public abstract class RecentsView extends PagedView impl return taskViewCount; } - /** - * Updates UI for a modal task, including hiding other tasks. - */ - public void updateUiForModalTask(TaskView taskView, boolean isTaskOverlayModal) { - int currentIndex = indexOfChild(taskView); - TaskView previousTask = getTaskViewAt(currentIndex - 1); - TaskView nextTask = getTaskViewAt(currentIndex + 1); - float alpha = isTaskOverlayModal ? 0.0f : 1.0f; - if (previousTask != null) { - previousTask.animate().alpha(alpha) - .translationX(isTaskOverlayModal ? previousTask.getWidth() / 2 : 0); - } - if (nextTask != null) { - nextTask.animate().alpha(alpha) - .translationX(isTaskOverlayModal ? -nextTask.getWidth() / 2 : 0); - - } - } - protected void onTaskStackUpdated() { } public void resetTaskVisuals() { @@ -776,6 +775,7 @@ public abstract class RecentsView extends PagedView impl updateCurveProperties(); // Update the set of visible task's data loadVisibleTaskData(); + setTaskModalness(0); } public void setFullscreenProgress(float fullscreenProgress) { @@ -1653,21 +1653,27 @@ public abstract class RecentsView extends PagedView impl mTempRect, mActivity.getDeviceProfile(), mTempPointF); setPivotX(mTempPointF.x); setPivotY(mTempPointF.y); - updateAdjacentPageOffset(); + updatePageOffsets(); } - private void updateAdjacentPageOffset() { + private void updatePageOffsets() { float offset = mAdjacentPageOffset * getWidth(); + float modalOffset = mTaskModalness * getWidth(); if (mIsRtl) { offset = -offset; + modalOffset = -modalOffset; } int count = getChildCount(); TaskView runningTask = mRunningTaskId == -1 ? null : getTaskView(mRunningTaskId); int midPoint = runningTask == null ? -1 : indexOfChild(runningTask); + int currentPage = getCurrentPage(); for (int i = 0; i < count; i++) { - getChildAt(i).setTranslationX(i == midPoint ? 0 : (i < midPoint ? -offset : offset)); + float translation = i == midPoint ? 0 : (i < midPoint ? -offset : offset); + float modalTranslation = + i == currentPage ? 0 : (i < currentPage ? -modalOffset : modalOffset); + getChildAt(i).setTranslationX(translation + modalTranslation); } updateCurveProperties(); } @@ -2113,6 +2119,18 @@ public abstract class RecentsView extends PagedView impl } } + /** + * 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. + */ + private void setTaskModalness(float modalness) { + mTaskModalness = modalness; + updatePageOffsets(); + if (getCurrentPageTaskView() != null) { + getCurrentPageTaskView().setModalness(modalness); + } + } + @Nullable protected DepthController getDepthController() { return null; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java index 4275933ae0..aea5b8e0ea 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java @@ -25,6 +25,7 @@ import static android.view.Gravity.TOP; import static android.widget.Toast.LENGTH_SHORT; import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION; +import static com.android.launcher3.Utilities.comp; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR; @@ -165,10 +166,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { private ObjectAnimator mIconAndDimAnimator; private float mIconScaleAnimStartProgress = 0; private float mFocusTransitionProgress = 1; + private float mModalness = 0; private float mStableAlpha = 1; private boolean mShowScreenshot; - private boolean mRunningModalAnimation = false; // The current background requests to load the task thumbnail and icon private TaskThumbnailCache.ThumbnailLoadRequest mThumbnailLoadRequest; @@ -239,59 +240,24 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { mIconView = findViewById(R.id.icon); } - public boolean isTaskOverlayModal() { - return mSnapshotView.getTaskOverlay().isOverlayModal(); - } - - /** Updates UI based on whether the task is modal. */ - public void updateUiForModalTask() { - boolean isOverlayModal = isTaskOverlayModal(); - mRunningModalAnimation = true; - if (getRecentsView() != null) { - getRecentsView().updateUiForModalTask(this, isOverlayModal); + /** + * The modalness of this view is how it should be displayed when it is shown on its own in the + * modal state of overview. + * + * @param modalness [0, 1] 0 being in context with other tasks, 1 being shown on its own. + */ + public void setModalness(float modalness) { + mModalness = modalness; + mIconView.setAlpha(comp(modalness)); + if (mContextualChip != null) { + mContextualChip.setScaleX(comp(modalness)); + mContextualChip.setScaleY(comp(modalness)); + } + if (mContextualChipWrapper != null) { + mContextualChipWrapper.setAlpha(comp(modalness)); } - // Hides footers and icon when overlay is modal. - if (isOverlayModal) { - for (FooterWrapper footer : mFooters) { - if (footer != null) { - footer.animateHide(); - } - } - if (mContextualChipWrapper != null) { - mContextualChipWrapper.animate().alpha(0f).setDuration(300); - } - if (mContextualChip != null) { - mContextualChip.animate().scaleX(0f).scaleY(0f).setDuration(300); - } - - mIconView.animate().alpha(0.0f); - } else { - if (mContextualChip != null) { - mContextualChip.animate().scaleX(1f).scaleY(1f).setDuration(300); - } - if (mContextualChipWrapper != null) { - mContextualChipWrapper.animate().alpha(1f).setDuration(300); - } - mIconView.animate().alpha(1.0f); - } - - // Sets animations for modal UI. We will remove the margins to zoom in the snapshot. - float topMargin = getResources().getDimension(R.dimen.task_thumbnail_top_margin); - float bottomMargin = - getResources().getDimension(R.dimen.task_thumbnail_bottom_margin_with_actions); - float newHeight = mSnapshotView.getHeight() + topMargin + bottomMargin; - float scale = isOverlayModal ? newHeight / mSnapshotView.getHeight() : 1.0f; - float centerDifference = (bottomMargin - topMargin) / 2; - float translationY = isOverlayModal ? centerDifference : 0; - this.animate().scaleX(scale).scaleY(scale).translationY(translationY) - .withEndAction(new Runnable() { - @Override - public void run() { - setCurveScale(scale); - mRunningModalAnimation = false; - } - }); + updateFooterVerticalOffset(mFooterVerticalOffset); } public TaskMenuView getMenuView() { @@ -535,12 +501,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { mIconView.setScaleX(scale); mIconView.setScaleY(scale); - mFooterVerticalOffset = 1.0f - scale; - for (FooterWrapper footer : mFooters) { - if (footer != null) { - footer.updateFooterOffset(); - } - } + updateFooterVerticalOffset(1.0f - scale); } public void setIconScaleAnimStartProgress(float startProgress) { @@ -586,6 +547,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { public void resetVisualProperties() { resetViewTransforms(); setFullscreenProgress(0); + setModalness(0); } public void setStableAlpha(float parentAlpha) { @@ -606,7 +568,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { @Override public void onPageScroll(ScrollState scrollState) { // Don't do anything if it's modal. - if (mRunningModalAnimation || isTaskOverlayModal()) { + if (mModalness > 0) { return; } @@ -759,6 +721,12 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { mStackHeight += footer.mView.getHeight(); } } + updateFooterVerticalOffset(0); + } + + private void updateFooterVerticalOffset(float offset) { + mFooterVerticalOffset = offset; + for (FooterWrapper footer : mFooters) { if (footer != null) { footer.updateFooterOffset(); @@ -857,7 +825,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } void updateFooterOffset() { - mAnimationOffset = Math.round(mStackHeight * mFooterVerticalOffset); + float offset = Utilities.or(mFooterVerticalOffset, mModalness); + mAnimationOffset = Math.round(mStackHeight * offset); mView.setTranslationY(mAnimationOffset + mEntryAnimationOffset + mCurrentFullscreenParams.mCurrentDrawnInsets.bottom + mCurrentFullscreenParams.mCurrentDrawnInsets.top); @@ -880,22 +849,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { animator.setDuration(100); animator.start(); } - - void animateHide() { - ValueAnimator animator = ValueAnimator.ofFloat(0.0f, 1.0f); - animator.addUpdateListener(anim -> { - mFooterVerticalOffset = anim.getAnimatedFraction(); - updateFooterOffset(); - }); - animator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - removeView(mView); - } - }); - animator.setDuration(100); - animator.start(); - } } private int getExpectedViewHeight(View view) { diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java index 33011acb09..ac50d6db8a 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java @@ -21,6 +21,7 @@ import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X; @@ -66,6 +67,7 @@ public abstract class BaseRecentsViewStateController getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0); OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim(); SCRIM_PROGRESS.set(scrim, state.getOverviewScrimAlpha(mLauncher)); + getTaskModalnessProperty().set(mRecentsView, state.getOverviewModalness()); } @Override @@ -101,8 +103,15 @@ public abstract class BaseRecentsViewStateController OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim(); setter.setFloat(scrim, SCRIM_PROGRESS, toState.getOverviewScrimAlpha(mLauncher), config.getInterpolator(ANIM_OVERVIEW_SCRIM_FADE, LINEAR)); + + setter.setFloat( + mRecentsView, getTaskModalnessProperty(), + toState.getOverviewModalness(), + config.getInterpolator(ANIM_OVERVIEW_MODAL, AGGRESSIVE_EASE_IN_OUT)); } + abstract FloatProperty getTaskModalnessProperty(); + /** * Get property for content alpha for the recents view. * diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java index 54d8f0d8bc..e2b867e138 100644 --- a/src/com/android/launcher3/LauncherState.java +++ b/src/com/android/launcher3/LauncherState.java @@ -36,6 +36,7 @@ import static com.android.launcher3.testing.TestProtocol.ALL_APPS_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.BACKGROUND_APP_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.HINT_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.NORMAL_STATE_ORDINAL; +import static com.android.launcher3.testing.TestProtocol.OVERVIEW_MODAL_TASK_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.OVERVIEW_PEEK_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.OVERVIEW_STATE_ORDINAL; import static com.android.launcher3.testing.TestProtocol.QUICK_SWITCH_STATE_ORDINAL; @@ -101,7 +102,7 @@ public abstract class LauncherState { } }; - private static final LauncherState[] sAllStates = new LauncherState[8]; + private static final LauncherState[] sAllStates = new LauncherState[9]; /** * TODO: Create a separate class for NORMAL state. @@ -128,6 +129,8 @@ public abstract class LauncherState { public static final LauncherState OVERVIEW = new OverviewState(OVERVIEW_STATE_ORDINAL); public static final LauncherState OVERVIEW_PEEK = OverviewState.newPeekState(OVERVIEW_PEEK_STATE_ORDINAL); + public static final LauncherState OVERVIEW_MODAL_TASK = OverviewState.newModalTaskState( + OVERVIEW_MODAL_TASK_STATE_ORDINAL); public static final LauncherState QUICK_SWITCH = OverviewState.newSwitchState(QUICK_SWITCH_STATE_ORDINAL); public static final LauncherState BACKGROUND_APP = @@ -279,6 +282,14 @@ public abstract class LauncherState { return 0; } + /** + * For this state, how modal should over view been shown. 0 modalness means all tasks drawn, + * 1 modalness means the current task is show on its own. + */ + public float getOverviewModalness() { + return 0; + } + /** * The amount of blur and wallpaper zoom to apply to the background of either the app * or Launcher surface in this state. Should be a number between 0 and 1, inclusive. diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 3c3ab6cc62..d95ccb43be 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -339,6 +339,30 @@ public final class Utilities { return min + (value * (max - min)); } + /** + * Bounds parameter to the range [0, 1] + */ + public static float saturate(float a) { + return boundToRange(a, 0, 1.0f); + } + + /** + * Returns the compliment (1 - a) of the parameter. + */ + public static float comp(float a) { + return 1 - a; + } + + /** + * Returns the "probabilistic or" of a and b. (a + b - ab). + * Useful beyond probability, can be used to combine two unit progresses for example. + */ + public static float or(float a, float b) { + float satA = saturate(a); + float satB = saturate(b); + return satA + satB - (satA * satB); + } + /** * Trims the string, removing all whitespace at the beginning and end of the string. * Non-breaking whitespaces are also removed. diff --git a/src/com/android/launcher3/states/StateAnimationConfig.java b/src/com/android/launcher3/states/StateAnimationConfig.java index 8dccbd3207..1c4986728f 100644 --- a/src/com/android/launcher3/states/StateAnimationConfig.java +++ b/src/com/android/launcher3/states/StateAnimationConfig.java @@ -69,6 +69,7 @@ public class StateAnimationConfig { ANIM_ALL_APPS_FADE, ANIM_OVERVIEW_SCRIM_FADE, ANIM_ALL_APPS_HEADER_FADE, + ANIM_OVERVIEW_MODAL }) @Retention(RetentionPolicy.SOURCE) public @interface AnimType {} @@ -85,8 +86,9 @@ public class StateAnimationConfig { public static final int ANIM_ALL_APPS_FADE = 10; public static final int ANIM_OVERVIEW_SCRIM_FADE = 11; public static final int ANIM_ALL_APPS_HEADER_FADE = 12; // e.g. predictions + public static final int ANIM_OVERVIEW_MODAL = 13; - private static final int ANIM_TYPES_COUNT = 13; + private static final int ANIM_TYPES_COUNT = 14; private final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT]; diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index a5a06b409c..fba6269097 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -28,10 +28,11 @@ public final class TestProtocol { public static final int SPRING_LOADED_STATE_ORDINAL = 1; public static final int OVERVIEW_STATE_ORDINAL = 2; public static final int OVERVIEW_PEEK_STATE_ORDINAL = 3; - public static final int QUICK_SWITCH_STATE_ORDINAL = 4; - public static final int ALL_APPS_STATE_ORDINAL = 5; - public static final int BACKGROUND_APP_STATE_ORDINAL = 6; - public static final int HINT_STATE_ORDINAL = 7; + public static final int OVERVIEW_MODAL_TASK_STATE_ORDINAL = 4; + public static final int QUICK_SWITCH_STATE_ORDINAL = 5; + public static final int ALL_APPS_STATE_ORDINAL = 6; + public static final int BACKGROUND_APP_STATE_ORDINAL = 7; + public static final int HINT_STATE_ORDINAL = 8; public static final String TAPL_EVENTS_TAG = "TaplEvents"; public static final String SEQUENCE_MAIN = "Main"; public static final String SEQUENCE_TIS = "TIS"; @@ -47,6 +48,8 @@ public final class TestProtocol { return "Overview"; case OVERVIEW_PEEK_STATE_ORDINAL: return "OverviewPeek"; + case OVERVIEW_MODAL_TASK_STATE_ORDINAL: + return "OverviewModalState"; case QUICK_SWITCH_STATE_ORDINAL: return "QuickSwitch"; case ALL_APPS_STATE_ORDINAL: diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java index e20b2ca1d2..507ff59b31 100644 --- a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java +++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java @@ -44,4 +44,11 @@ public class OverviewState extends LauncherState { public static OverviewState newSwitchState(int id) { return new OverviewState(id); } + + /** + * New Overview substate that represents the overview in modal mode (one task shown on its own) + */ + public static OverviewState newModalTaskState(int id) { + return new OverviewState(id); + } }