diff --git a/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java b/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java index 7c97b93b03..5471e492ae 100644 --- a/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java +++ b/quickstep/robolectric_tests/src/com/android/launcher3/model/WidgetsPredicationUpdateTaskTest.java @@ -48,6 +48,7 @@ import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.shadows.ShadowDeviceFlag; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.IntArray; +import com.android.launcher3.util.IntSet; import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.LauncherModelHelper; import com.android.launcher3.util.ViewOnDrawExecutor; @@ -239,8 +240,8 @@ public final class WidgetsPredicationUpdateTaskTest { } @Override - public int getPageToBindSynchronously() { - return 0; + public IntSet getPagesToBindSynchronously() { + return IntSet.wrap(0); } @Override @@ -259,7 +260,7 @@ public final class WidgetsPredicationUpdateTaskTest { public void finishFirstPageBind(ViewOnDrawExecutor executor) { } @Override - public void finishBindingItems(int pageBoundFirst) { } + public void finishBindingItems(IntSet pagesBoundFirst) { } @Override public void preAddApps() { } @@ -287,7 +288,7 @@ public final class WidgetsPredicationUpdateTaskTest { public void bindAllWidgets(List widgets) { } @Override - public void onPageBoundSynchronously(int page) { } + public void onPagesBoundSynchronously(IntSet pages) { } @Override public void executeOnNextDraw(ViewOnDrawExecutor executor) { } diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java index 0b41f15b42..67a42252cd 100644 --- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java @@ -55,6 +55,7 @@ import com.android.launcher3.taskbar.TaskbarManager; import com.android.launcher3.taskbar.TaskbarStateHandler; import com.android.launcher3.uioverrides.RecentsViewStateController; import com.android.launcher3.util.ActivityOptionsWrapper; +import com.android.launcher3.util.IntSet; import com.android.launcher3.util.ObjectWrapper; import com.android.launcher3.util.UiThreadHelper; import com.android.quickstep.RecentsModel; @@ -410,8 +411,8 @@ public abstract class BaseQuickstepLauncher extends Launcher } @Override - public void finishBindingItems(int pageBoundFirst) { - super.finishBindingItems(pageBoundFirst); + public void finishBindingItems(IntSet pagesBoundFirst) { + super.finishBindingItems(pagesBoundFirst); // Instantiate and initialize WellbeingModel now that its loading won't interfere with // populating workspace. // TODO: Find a better place for this diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java index 80754a00f4..ec77b9b902 100644 --- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java +++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java @@ -691,7 +691,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener floatingIconBounds.right += offsetX; floatingIconBounds.bottom += offsetY; - SurfaceParams[] params = new SurfaceParams[appTargets.length]; + ArrayList params = new ArrayList<>(); for (int i = appTargets.length - 1; i >= 0; i--) { RemoteAnimationTargetCompat target = appTargets[i]; SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash); @@ -743,9 +743,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener .withWindowCrop(crop) .withAlpha(1f); } - params[i] = builder.build(); + params.add(builder.build()); } - surfaceApplier.scheduleApply(params); if (navBarTarget != null) { final SurfaceParams.Builder navBuilder = @@ -759,8 +758,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener } else { navBuilder.withAlpha(mNavFadeOut.value); } - surfaceApplier.scheduleApply(navBuilder.build()); + params.add(navBuilder.build()); } + + surfaceApplier.scheduleApply(params.toArray(new SurfaceParams[params.size()])); } }); @@ -791,6 +792,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener SurfaceTransactionApplier surfaceApplier = new SurfaceTransactionApplier(floatingView); openingTargets.addReleaseCheck(surfaceApplier); + RemoteAnimationTargetCompat navBarTarget = openingTargets.getNavBarRemoteAnimationTarget(); + AnimatorSet animatorSet = new AnimatorSet(); ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); appAnimator.setDuration(APP_LAUNCH_DURATION); @@ -832,6 +835,11 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener windowTargetBounds.height(), 0 /* delay */, APP_LAUNCH_DURATION, EXAGGERATED_EASE); + final FloatProp mNavFadeOut = new FloatProp(1f, 0f, 0, ANIMATION_NAV_FADE_OUT_DURATION, + NAV_FADE_OUT_INTERPOLATOR); + final FloatProp mNavFadeIn = new FloatProp(0f, 1f, ANIMATION_DELAY_NAV_FADE_IN, + ANIMATION_NAV_FADE_IN_DURATION, NAV_FADE_IN_INTERPOLATOR); + @Override public void onUpdate(float percent) { widgetBackgroundBounds.set(mDx.value - mWidth.value / 2f, @@ -847,7 +855,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener matrix.postScale(mAppWindowScale, mAppWindowScale, widgetBackgroundBounds.left, widgetBackgroundBounds.top); - SurfaceParams[] params = new SurfaceParams[appTargets.length]; + ArrayList params = new ArrayList<>(); float floatingViewAlpha = appTargetsAreTranslucent ? 1 - mPreviewAlpha.value : 1; for (int i = appTargets.length - 1; i >= 0; i--) { RemoteAnimationTargetCompat target = appTargets[i]; @@ -861,9 +869,23 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener .withAlpha(mPreviewAlpha.value) .withCornerRadius(mWindowRadius.value / mAppWindowScale); } - params[i] = builder.build(); + params.add(builder.build()); } - surfaceApplier.scheduleApply(params); + + if (navBarTarget != null) { + final SurfaceParams.Builder navBuilder = + new SurfaceParams.Builder(navBarTarget.leash); + if (mNavFadeIn.value > mNavFadeIn.getStartValue()) { + navBuilder.withMatrix(matrix) + .withWindowCrop(appWindowCrop) + .withAlpha(mNavFadeIn.value); + } else { + navBuilder.withAlpha(mNavFadeOut.value); + } + params.add(navBuilder.build()); + } + + surfaceApplier.scheduleApply(params.toArray(new SurfaceParams[params.size()])); } }); diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index 996d36aadc..6cad3ddc92 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -106,8 +106,7 @@ public final class RecentsViewStateController extends float clearAllButtonAlpha = state.areElementsVisible(mLauncher, CLEAR_ALL_BUTTON) ? 1 : 0; propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA, clearAllButtonAlpha, LINEAR); - float overviewButtonAlpha = state.areElementsVisible(mLauncher, OVERVIEW_ACTIONS) - && mRecentsView.shouldShowOverviewActionsForState(state) ? 1 : 0; + float overviewButtonAlpha = state.areElementsVisible(mLauncher, OVERVIEW_ACTIONS) ? 1 : 0; propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(), MultiValueAlpha.VALUE, overviewButtonAlpha, config.getInterpolator( ANIM_OVERVIEW_ACTIONS_FADE, LINEAR)); diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java index f0364eb410..52083bbd8f 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java @@ -77,9 +77,7 @@ public class FallbackRecentsStateController implements StateHandler mSizeStrategy; @@ -348,6 +348,13 @@ public abstract class RecentsView 0) { + mFocusedTaskId = getTaskViewAt(0).getTaskId(); + } updateTaskSize(); if (mNextPage == INVALID_PAGE) { @@ -1166,7 +1176,7 @@ public abstract class RecentsView= 0; i--) { TaskView taskView = getTaskViewAt(i); - if (mIgnoreResetTaskId != taskView.getTask().key.id) { + if (mIgnoreResetTaskId != taskView.getTaskId()) { taskView.resetViewTransforms(); taskView.setStableAlpha(mContentAlpha); taskView.setFullscreenProgress(mFullscreenProgress); @@ -1285,6 +1295,11 @@ public abstract class RecentsView 0 ? getTaskViewAt(0).getTaskId() : -1; if (mRecentsAnimationController != null) { if (LIVE_TILE.get() && mEnableDrawingLiveTile) { @@ -1579,6 +1611,10 @@ public abstract class RecentsView v.getVisibility() != GONE && v != taskView); - int taskCount = getTaskViewCount(); int scrollDiffPerPage = 0; - if (count > 1) { - scrollDiffPerPage = Math.abs(oldScroll[1] - oldScroll[0]); - } - int draggedIndex = indexOfChild(taskView); - - boolean isFocusedTaskDismissed = taskView.getTask().key.id == mFocusedTaskId; - if (isFocusedTaskDismissed && showAsGrid()) { - anim.setFloat(mActionsView, VIEW_ALPHA, 0, clampToProgress(ACCEL_0_5, 0, 0.5f)); - } - float dismissedTaskWidth = taskView.getLayoutParams().width + mPageSpacing; boolean needsCurveUpdates = false; + + if (showAsGrid) { + dismissedTaskWidth = dismissedTaskView.getLayoutParams().width + mPageSpacing; + isFocusedTaskDismissed = dismissedTaskId == mFocusedTaskId; + if (isFocusedTaskDismissed) { + nextFocusedTaskFromTop = + mTopRowIdSet.size() > 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f; + // Pick the next focused task from the preferred row. + for (int i = 0; i < taskCount; i++) { + TaskView taskView = getTaskViewAt(i); + if (taskView == dismissedTaskView) { + continue; + } + boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskId()); + if ((nextFocusedTaskFromTop && isTopRow + || (!nextFocusedTaskFromTop && !isTopRow))) { + nextFocusedTaskView = taskView; + break; + } + } + if (nextFocusedTaskView != null) { + nextFocusedTaskWidth = + nextFocusedTaskView.getLayoutParams().width + mPageSpacing; + } + } + } else { + getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC); + getPageScrolls(newScroll, false, + v -> v.getVisibility() != GONE && v != dismissedTaskView); + if (count > 1) { + scrollDiffPerPage = Math.abs(oldScroll[1] - oldScroll[0]); + } + } + + int distanceFromDismissedTask = 0; for (int i = 0; i < count; i++) { View child = getChildAt(i); - if (child == taskView) { + if (child == dismissedTaskView) { if (animateTaskView) { - addDismissedTaskAnimations(taskView, duration, anim); + addDismissedTaskAnimations(dismissedTaskView, duration, anim); } - } else if (!showAsGrid()) { + } else if (!showAsGrid) { // Compute scroll offsets from task dismissal for animation. // If we just take newScroll - oldScroll, everything to the right of dragged task // translates to the left. We need to offset this in some cases: @@ -2242,15 +2314,15 @@ public abstract class RecentsView= dismissed index and in the same row as the - // dismissed index, or if the dismissed task was the focused task. Offset - // successive task dismissal durations for a staggered effect. - if (isFocusedTaskDismissed || (i >= draggedIndex && isSameGridRow((TaskView) child, - taskView))) { - FloatProperty translationProperty = - ((TaskView) child).getPrimaryDismissTranslationProperty(); - float additionalDismissDuration = - ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * Math.abs( - i - draggedIndex); - anim.setFloat(child, translationProperty, - !mIsRtl ? -dismissedTaskWidth : dismissedTaskWidth, - clampToProgress(LINEAR, Utilities.boundToRange( - INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET - + additionalDismissDuration, 0f, 1f), 1)); + // dismissed index or next focused index. Offset successive task dismissal + // durations for a staggered effect. + float animationStartProgress = Utilities.boundToRange( + INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + + ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + * ++distanceFromDismissedTask, 0f, 1f); + if (taskView == nextFocusedTaskView) { + // Enlarge the task to be focused next, and translate into focus position. + float scale = mTaskWidth / (float) mLastComputedGridTaskSize.width(); + anim.setFloat(taskView, TaskView.SNAPSHOT_SCALE, scale, + clampToProgress(LINEAR, animationStartProgress, 1f)); + anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), + mIsRtl ? dismissedTaskWidth : -dismissedTaskWidth, + clampToProgress(LINEAR, animationStartProgress, 1f)); + float secondaryTranslation = -mTaskGridVerticalDiff; + if (!nextFocusedTaskFromTop) { + secondaryTranslation -= mTopBottomRowHeightDiff; + } + anim.setFloat(taskView, taskView.getSecondaryDissmissTranslationProperty(), + secondaryTranslation, + clampToProgress(LINEAR, animationStartProgress, 1f)); + anim.setFloat(taskView, TaskView.FOCUS_TRANSITION, 0f, + clampToProgress(LINEAR, 0f, ANIMATION_DISMISS_PROGRESS_MIDPOINT)); + } else { + float primaryTranslation = + isFocusedTaskDismissed ? nextFocusedTaskWidth : dismissedTaskWidth; + anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), + mIsRtl ? primaryTranslation : -primaryTranslation, + clampToProgress(LINEAR, animationStartProgress, 1f)); } } } @@ -2295,14 +2392,15 @@ public abstract class RecentsView() { @Override public void accept(Boolean success) { - if (LIVE_TILE.get() && mEnableDrawingLiveTile && taskView.isRunningTask() + if (LIVE_TILE.get() && mEnableDrawingLiveTile && dismissedTaskView.isRunningTask() && success) { finishRecentsAnimation(true /* toHome */, () -> onEnd(success)); } else { @@ -2314,11 +2412,11 @@ public abstract class RecentsView ActivityManagerWrapper.getInstance() - .removeTask(taskView.getTask().key.id)); + .removeTask(dismissedTaskId)); mActivity.getStatsLogManager().logger() - .withItemInfo(taskView.getItemInfo()) + .withItemInfo(dismissedTaskView.getItemInfo()) .log(LAUNCHER_TASK_DISMISS_SWIPE_UP); } } @@ -2328,31 +2426,31 @@ public abstract class RecentsView