diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java index c44ccd3ded..b07f8af41f 100644 --- a/quickstep/src/com/android/quickstep/QuickScrubController.java +++ b/quickstep/src/com/android/quickstep/QuickScrubController.java @@ -126,11 +126,13 @@ public class QuickScrubController implements OnAlarmListener { if (mIsQuickSwitch) { mShouldSwitchToNext = true; mPrevProgressDelta = 0; - if (mRecentsView.getTaskViewCount() > 0) { - mRecentsView.getTaskViewAt(0).setFullscreen(true); + TaskView runningTaskView = mRecentsView.getRunningTaskView(); + TaskView nextTaskView = mRecentsView.getNextTaskView(); + if (runningTaskView != null) { + runningTaskView.setFullscreenProgress(1); } - if (mRecentsView.getTaskViewCount() > 1) { - mRecentsView.getTaskViewAt(1).setFullscreen(true); + if (nextTaskView != null) { + nextTaskView.setFullscreenProgress(1); } } @@ -161,11 +163,13 @@ public class QuickScrubController implements OnAlarmListener { mWaitingForTaskLaunch = false; if (mIsQuickSwitch) { mIsQuickSwitch = false; - if (mRecentsView.getTaskViewCount() > 0) { - mRecentsView.getTaskViewAt(0).setFullscreen(false); + TaskView runningTaskView = mRecentsView.getRunningTaskView(); + TaskView nextTaskView = mRecentsView.getNextTaskView(); + if (runningTaskView != null) { + runningTaskView.setFullscreenProgress(0); } - if (mRecentsView.getTaskViewCount() > 1) { - mRecentsView.getTaskViewAt(1).setFullscreen(false); + if (nextTaskView != null) { + nextTaskView.setFullscreenProgress(0); } } @@ -267,12 +271,12 @@ public class QuickScrubController implements OnAlarmListener { public void onQuickScrubProgress(float progress) { if (mIsQuickSwitch) { - TaskView currentPage = mRecentsView.getTaskViewAt(0); - TaskView nextPage = mRecentsView.getTaskViewAt(1); + TaskView currentPage = mRecentsView.getRunningTaskView(); + TaskView nextPage = mRecentsView.getNextTaskView(); if (currentPage == null || nextPage == null) { return; } - if (!mFinishedTransitionToQuickScrub) { + if (!mFinishedTransitionToQuickScrub || mStartProgress <= 0) { mStartProgress = mEndProgress = progress; } else { float progressDelta = progress - mEndProgress; diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index c403e274e2..98e26ef040 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -615,6 +615,11 @@ public class WindowTransformSwipeHandler { HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } } + // Update insets of the next previous task, as we might switch to it. + TaskView nextTaskView = mRecentsView == null ? null : mRecentsView.getNextTaskView(); + if (mInteractionType == INTERACTION_NORMAL && nextTaskView != null) { + nextTaskView.setFullscreenProgress(1 - mCurrentShift.value); + } if (mLauncherTransitionController == null || mLauncherTransitionController .getAnimationPlayer().isStarted()) { diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 854e7288b7..7842fa423b 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -760,14 +760,14 @@ public abstract class RecentsView extends PagedView impl if (runningTaskView == null) { // Launch the first task if (getTaskViewCount() > 0) { - ((TaskView) getChildAt(0)).launchTask(true /* animate */); + getTaskViewAt(0).launchTask(true /* animate */); } } else { - // Get the next launch task - int runningTaskIndex = indexOfChild(runningTaskView); - int nextTaskIndex = Math.max(0, Math.min(getTaskViewCount() - 1, runningTaskIndex + 1)); - if (nextTaskIndex < getTaskViewCount()) { - ((TaskView) getChildAt(nextTaskIndex)).launchTask(true /* animate */); + TaskView nextTaskView = getNextTaskView(); + if (nextTaskView != null) { + nextTaskView.launchTask(true /* animate */); + } else { + runningTaskView.launchTask(true /* animate */); } } } @@ -1140,6 +1140,19 @@ public abstract class RecentsView extends PagedView impl child.setAlpha(mContentAlpha); } + /** + * @return The most recent task that is older than the currently running task. If there is + * currently no running task or there is no task older than it, then return null. + */ + @Nullable + public TaskView getNextTaskView() { + TaskView runningTaskView = getRunningTaskView(); + if (runningTaskView == null) { + return null; + } + return getTaskViewAt(indexOfChild(runningTaskView) + 1); + } + public TaskView getTaskViewAt(int index) { View child = getChildAt(index); return child == mClearAllButton ? null : (TaskView) child; @@ -1261,12 +1274,14 @@ public abstract class RecentsView extends PagedView impl toScale, toTranslationY); scaleAndTranslation[1] = -scaleAndTranslation[1]; anim.play(createAnimForChild(adjacentTask, scaleAndTranslation)); + anim.play(ObjectAnimator.ofFloat(adjacentTask, TaskView.FULLSCREEN_PROGRESS, 1)); } if (taskIndex + 1 < getTaskViewCount()) { TaskView adjacentTask = getTaskViewAt(taskIndex + 1); float[] scaleAndTranslation = getAdjacentScaleAndTranslation(centerTask, toScale, toTranslationY); anim.play(createAnimForChild(adjacentTask, scaleAndTranslation)); + anim.play(ObjectAnimator.ofFloat(adjacentTask, TaskView.FULLSCREEN_PROGRESS, 1)); } } else { // We are launching an adjacent task, so parallax the center and other adjacent task. diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java index 6c5ddd84e0..c2403a363c 100644 --- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java @@ -81,6 +81,7 @@ public class TaskThumbnailView extends View { private float mClipBottom = -1; private Rect mScaledInsets = new Rect(); + private boolean mIsRotated; private Task mTask; private ThumbnailData mThumbnailData; @@ -144,7 +145,7 @@ public class TaskThumbnailView extends View { /** * Sets the alpha of the dim layer on top of this view. - * + *

* If dimAlpha is 0, no dimming is applied; if dimAlpha is 1, the thumbnail will be black. */ public void setDimAlpha(float dimAlpha) { @@ -188,13 +189,18 @@ public class TaskThumbnailView extends View { @Override protected void onDraw(Canvas canvas) { - if (((TaskView) getParent()).isFullscreen()) { + float fullscreenProgress = ((TaskView) getParent()).getFullscreenProgress(); + if (mIsRotated) { + // Don't show insets in the wrong orientation. + fullscreenProgress = 0; + } + if (fullscreenProgress > 0) { // Draw the insets if we're being drawn fullscreen (we do this for quick switch). drawOnCanvas(canvas, - -mScaledInsets.left, - -mScaledInsets.top, - getMeasuredWidth() + mScaledInsets.right, - getMeasuredHeight() + mScaledInsets.bottom, + -mScaledInsets.left * fullscreenProgress, + -mScaledInsets.top * fullscreenProgress, + getMeasuredWidth() + mScaledInsets.right * fullscreenProgress, + getMeasuredHeight() + mScaledInsets.bottom * fullscreenProgress, mCornerRadius); } else { drawOnCanvas(canvas, 0, 0, getMeasuredWidth(), getMeasuredHeight(), mCornerRadius); @@ -241,11 +247,11 @@ public class TaskThumbnailView extends View { } private void updateThumbnailMatrix() { - boolean rotate = false; + mIsRotated = false; mClipBottom = -1; if (mBitmapShader != null && mThumbnailData != null) { float scale = mThumbnailData.scale; - Rect thumbnailInsets = mThumbnailData.insets; + Rect thumbnailInsets = mThumbnailData.insets; final float thumbnailWidth = mThumbnailData.thumbnail.getWidth() - (thumbnailInsets.left + thumbnailInsets.right) * scale; final float thumbnailHeight = mThumbnailData.thumbnail.getHeight() - @@ -262,12 +268,12 @@ public class TaskThumbnailView extends View { final Configuration configuration = getContext().getResources().getConfiguration(); // Rotate the screenshot if not in multi-window mode - rotate = FeatureFlags.OVERVIEW_USE_SCREENSHOT_ORIENTATION && + mIsRotated = FeatureFlags.OVERVIEW_USE_SCREENSHOT_ORIENTATION && configuration.orientation != mThumbnailData.orientation && !mActivity.isInMultiWindowModeCompat() && mThumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN; // Scale the screenshot to always fit the width of the card. - thumbnailScale = rotate + thumbnailScale = mIsRotated ? getMeasuredWidth() / thumbnailHeight : getMeasuredWidth() / thumbnailWidth; } @@ -275,7 +281,7 @@ public class TaskThumbnailView extends View { mScaledInsets.set(thumbnailInsets); Utilities.scaleRect(mScaledInsets, thumbnailScale); - if (rotate) { + if (mIsRotated) { int rotationDir = profile.isVerticalBarLayout() && !profile.isSeascape() ? -1 : 1; mMatrix.setRotate(90 * rotationDir); int newLeftInset = rotationDir == 1 ? thumbnailInsets.bottom : thumbnailInsets.top; @@ -299,7 +305,7 @@ public class TaskThumbnailView extends View { mMatrix.postScale(thumbnailScale, thumbnailScale); mBitmapShader.setLocalMatrix(mMatrix); - float bitmapHeight = Math.max((rotate ? thumbnailWidth : thumbnailHeight) + float bitmapHeight = Math.max((mIsRotated ? thumbnailWidth : thumbnailHeight) * thumbnailScale, 0); if (Math.round(bitmapHeight) < getMeasuredHeight()) { mClipBottom = bitmapHeight; @@ -307,7 +313,7 @@ public class TaskThumbnailView extends View { mPaint.setShader(mBitmapShader); } - if (rotate) { + if (mIsRotated) { // The overlay doesn't really work when the screenshot is rotated, so don't add it. mOverlay.reset(); } else { diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index c2d7d787e4..bb6f514597 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -102,6 +102,19 @@ public class TaskView extends FrameLayout implements PageCallbacks { } }; + public static final FloatProperty FULLSCREEN_PROGRESS = + new FloatProperty("fullscreenProgress") { + @Override + public void setValue(TaskView taskView, float v) { + taskView.setFullscreenProgress(v); + } + + @Override + public Float get(TaskView taskView) { + return taskView.mFullscreenProgress; + } + }; + private static final FloatProperty FOCUS_TRANSITION = new FloatProperty("focusTransition") { @Override @@ -140,7 +153,7 @@ public class TaskView extends FrameLayout implements PageCallbacks { private DigitalWellBeingToast mDigitalWellBeingToast; private float mCurveScale; private float mZoomScale; - private boolean mIsFullscreen; + private float mFullscreenProgress; private Animator mIconAndDimAnimator; private float mFocusTransitionProgress = 1; @@ -341,6 +354,10 @@ public class TaskView extends FrameLayout implements PageCallbacks { setTranslationZ(0); setAlpha(1f); setIconScaleAndDim(1); + if (!getRecentsView().getQuickScrubController().isQuickSwitch()) { + // Reset full screen progress unless we are doing back to back quick switch. + setFullscreenProgress(0); + } } @Override @@ -499,15 +516,21 @@ public class TaskView extends FrameLayout implements PageCallbacks { /** * Hides the icon and shows insets when this TaskView is about to be shown fullscreen. + * @param progress: 0 = show icon and no insets; 1 = don't show icon and show full insets. */ - public void setFullscreen(boolean isFullscreen) { - mIsFullscreen = isFullscreen; - mIconView.setVisibility(mIsFullscreen ? INVISIBLE : VISIBLE); - setClipChildren(!mIsFullscreen); - setClipToPadding(!mIsFullscreen); + public void setFullscreenProgress(float progress) { + if (progress == mFullscreenProgress) { + return; + } + mFullscreenProgress = progress; + boolean isFullscreen = mFullscreenProgress > 0; + mIconView.setVisibility(isFullscreen ? INVISIBLE : VISIBLE); + setClipChildren(!isFullscreen); + setClipToPadding(!isFullscreen); + getThumbnail().invalidate(); } - public boolean isFullscreen() { - return mIsFullscreen; + public float getFullscreenProgress() { + return mFullscreenProgress; } }