Loading quickstep/src/com/android/quickstep/util/SplitAnimationController.kt +48 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.animation.ObjectAnimator import android.animation.ValueAnimator import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW import android.content.Context import android.graphics.Bitmap import android.graphics.Rect import android.graphics.RectF Loading @@ -41,8 +42,10 @@ import androidx.annotation.VisibleForTesting import com.android.app.animation.Interpolators import com.android.launcher3.DeviceProfile import com.android.launcher3.Flags.enableOverviewIconMenu import com.android.launcher3.InsettableFrameLayout import com.android.launcher3.Launcher import com.android.launcher3.QuickstepTransitionManager import com.android.launcher3.R import com.android.launcher3.Utilities import com.android.launcher3.anim.PendingAnimation import com.android.launcher3.apppairs.AppPairIcon Loading Loading @@ -268,6 +271,51 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC } } /** * Creates and returns a view to fade in at .4 animation progress and adds it to the provided * [pendingAnimation]. Assumes that animation will be the final split placeholder launch anim. * * [secondPlaceholderEndingBounds] refers to the second placeholder view that gets added on * screen, not the logical second app. * For landscape it's the left app and for portrait the top one. */ fun addDividerPlaceholderViewToAnim(pendingAnimation: PendingAnimation, launcher: StatefulActivity<*>, secondPlaceholderEndingBounds: Rect, context: Context) : View { val mSplitDividerPlaceholderView = View(context) val recentsView = launcher.getOverviewPanel<RecentsView<*, *>>() val dp : com.android.launcher3.DeviceProfile = launcher.getDeviceProfile() // Add it before/under the most recently added first floating taskView val firstAddedSplitViewIndex: Int = launcher.getDragLayer().indexOfChild( recentsView.splitSelectController.firstFloatingTaskView) launcher.getDragLayer().addView(mSplitDividerPlaceholderView, firstAddedSplitViewIndex) val lp = mSplitDividerPlaceholderView.layoutParams as InsettableFrameLayout.LayoutParams lp.topMargin = 0 if (dp.isLeftRightSplit) { lp.height = secondPlaceholderEndingBounds.height() lp.width = launcher.resources .getDimensionPixelSize(R.dimen.split_divider_handle_region_height) mSplitDividerPlaceholderView.translationX = secondPlaceholderEndingBounds.right - lp.width / 2f mSplitDividerPlaceholderView.translationY = 0f } else { lp.height = launcher.resources .getDimensionPixelSize(R.dimen.split_divider_handle_region_height) lp.width = secondPlaceholderEndingBounds.width() mSplitDividerPlaceholderView.translationY = secondPlaceholderEndingBounds.top - lp.height / 2f mSplitDividerPlaceholderView.translationX = 0f } mSplitDividerPlaceholderView.alpha = 0f mSplitDividerPlaceholderView.setBackgroundColor(launcher.resources .getColor(R.color.taskbar_background_dark)) val timings = AnimUtils.getDeviceSplitToConfirmTimings(dp.isTablet) pendingAnimation.setViewAlpha(mSplitDividerPlaceholderView, 1f, Interpolators.clampToProgress(timings.stagedRectScaleXInterpolator, 0.4f, 1f)) return mSplitDividerPlaceholderView } /** Does not play any animation if user is not currently in split selection state. */ fun playPlaceholderDismissAnim(launcher: StatefulActivity<*>, splitDismissEvent: EventEnum) { if (!splitSelectStateController.isSplitSelectActive) { Loading quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java +5 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,10 @@ public class SplitToWorkspaceController { new RectF(firstTaskStartingBounds), firstTaskEndingBounds, false /* fadeWithThumbnail */, true /* isStagedTask */); View mSplitDividerPlaceholderView = recentsView.getSplitSelectController() .getSplitAnimationController().addDividerPlaceholderViewToAnim(pendingAnimation, mLauncher, secondTaskEndingBounds, view.getContext()); FloatingTaskView secondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mLauncher, view, bitmap, icon, secondTaskStartingBounds); secondFloatingTaskView.setAlpha(1); Loading Loading @@ -192,6 +196,7 @@ public class SplitToWorkspaceController { private void cleanUp() { mLauncher.getDragLayer().removeView(firstFloatingTaskView); mLauncher.getDragLayer().removeView(secondFloatingTaskView); mLauncher.getDragLayer().removeView(mSplitDividerPlaceholderView); mController.getSplitAnimationController().removeSplitInstructionsView(mLauncher); mController.resetState(); } Loading quickstep/src/com/android/quickstep/views/FloatingTaskView.java +0 −1 Original line number Diff line number Diff line Loading @@ -299,7 +299,6 @@ public class FloatingTaskView extends FrameLayout { ValueAnimator transitionAnimator = ValueAnimator.ofFloat(0, 1); animation.add(transitionAnimator); long animDuration = animation.getDuration(); RectF floatingTaskViewBounds = new RectF(); if (fadeWithThumbnail) { Loading quickstep/src/com/android/quickstep/views/RecentsView.java +6 −1 Original line number Diff line number Diff line Loading @@ -61,7 +61,6 @@ import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_RIGHT; import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_TAB; import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_UP; import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA; import static com.android.window.flags.Flags.enableDesktopWindowingMode; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_ACTIONS_IN_MENU; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_DESKTOP; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION; Loading @@ -69,6 +68,7 @@ import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SELECT_ACTIVE; import static com.android.window.flags.Flags.enableDesktopWindowingMode; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; Loading Loading @@ -721,6 +721,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T private int mSplitHiddenTaskViewIndex = -1; @Nullable private FloatingTaskView mSecondFloatingTaskView; private View mSplitDividerPlaceholderView; /** * The task to be removed and immediately re-added. Should not be added to task pool. Loading Loading @@ -4839,6 +4840,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T mSplitSelectStateController.getActiveSplitStagePosition(), firstTaskEndingBounds, secondTaskEndingBounds); mSplitDividerPlaceholderView = mSplitSelectStateController .getSplitAnimationController().addDividerPlaceholderViewToAnim(pendingAnimation, mActivity, secondTaskEndingBounds, getContext()); FloatingTaskView firstFloatingTaskView = mSplitSelectStateController.getFirstFloatingTaskView(); firstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds); Loading Loading @@ -4893,6 +4897,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T safeRemoveDragLayerView(mSplitSelectStateController.getFirstFloatingTaskView()); safeRemoveDragLayerView(mSecondFloatingTaskView); safeRemoveDragLayerView(mSplitSelectStateController.getSplitInstructionsView()); safeRemoveDragLayerView(mSplitDividerPlaceholderView); mSecondFloatingTaskView = null; mSplitSelectSource = null; mSplitSelectStateController.getSplitAnimationController() Loading res/color/taskbar_background_dark.xml 0 → 100644 +21 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2024 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. --> <!-- Should be the same as in packages/apps/Launcher3/res/color-night-v31/taskbar_background.xml --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Want to use @android:color/system_neutral1_500, but that causes build errors --> <item android:color="#76777D" android:lStar="6" /> </selector> No newline at end of file Loading
quickstep/src/com/android/quickstep/util/SplitAnimationController.kt +48 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.animation.ObjectAnimator import android.animation.ValueAnimator import android.app.ActivityManager.RunningTaskInfo import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW import android.content.Context import android.graphics.Bitmap import android.graphics.Rect import android.graphics.RectF Loading @@ -41,8 +42,10 @@ import androidx.annotation.VisibleForTesting import com.android.app.animation.Interpolators import com.android.launcher3.DeviceProfile import com.android.launcher3.Flags.enableOverviewIconMenu import com.android.launcher3.InsettableFrameLayout import com.android.launcher3.Launcher import com.android.launcher3.QuickstepTransitionManager import com.android.launcher3.R import com.android.launcher3.Utilities import com.android.launcher3.anim.PendingAnimation import com.android.launcher3.apppairs.AppPairIcon Loading Loading @@ -268,6 +271,51 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC } } /** * Creates and returns a view to fade in at .4 animation progress and adds it to the provided * [pendingAnimation]. Assumes that animation will be the final split placeholder launch anim. * * [secondPlaceholderEndingBounds] refers to the second placeholder view that gets added on * screen, not the logical second app. * For landscape it's the left app and for portrait the top one. */ fun addDividerPlaceholderViewToAnim(pendingAnimation: PendingAnimation, launcher: StatefulActivity<*>, secondPlaceholderEndingBounds: Rect, context: Context) : View { val mSplitDividerPlaceholderView = View(context) val recentsView = launcher.getOverviewPanel<RecentsView<*, *>>() val dp : com.android.launcher3.DeviceProfile = launcher.getDeviceProfile() // Add it before/under the most recently added first floating taskView val firstAddedSplitViewIndex: Int = launcher.getDragLayer().indexOfChild( recentsView.splitSelectController.firstFloatingTaskView) launcher.getDragLayer().addView(mSplitDividerPlaceholderView, firstAddedSplitViewIndex) val lp = mSplitDividerPlaceholderView.layoutParams as InsettableFrameLayout.LayoutParams lp.topMargin = 0 if (dp.isLeftRightSplit) { lp.height = secondPlaceholderEndingBounds.height() lp.width = launcher.resources .getDimensionPixelSize(R.dimen.split_divider_handle_region_height) mSplitDividerPlaceholderView.translationX = secondPlaceholderEndingBounds.right - lp.width / 2f mSplitDividerPlaceholderView.translationY = 0f } else { lp.height = launcher.resources .getDimensionPixelSize(R.dimen.split_divider_handle_region_height) lp.width = secondPlaceholderEndingBounds.width() mSplitDividerPlaceholderView.translationY = secondPlaceholderEndingBounds.top - lp.height / 2f mSplitDividerPlaceholderView.translationX = 0f } mSplitDividerPlaceholderView.alpha = 0f mSplitDividerPlaceholderView.setBackgroundColor(launcher.resources .getColor(R.color.taskbar_background_dark)) val timings = AnimUtils.getDeviceSplitToConfirmTimings(dp.isTablet) pendingAnimation.setViewAlpha(mSplitDividerPlaceholderView, 1f, Interpolators.clampToProgress(timings.stagedRectScaleXInterpolator, 0.4f, 1f)) return mSplitDividerPlaceholderView } /** Does not play any animation if user is not currently in split selection state. */ fun playPlaceholderDismissAnim(launcher: StatefulActivity<*>, splitDismissEvent: EventEnum) { if (!splitSelectStateController.isSplitSelectActive) { Loading
quickstep/src/com/android/quickstep/util/SplitToWorkspaceController.java +5 −0 Original line number Diff line number Diff line Loading @@ -162,6 +162,10 @@ public class SplitToWorkspaceController { new RectF(firstTaskStartingBounds), firstTaskEndingBounds, false /* fadeWithThumbnail */, true /* isStagedTask */); View mSplitDividerPlaceholderView = recentsView.getSplitSelectController() .getSplitAnimationController().addDividerPlaceholderViewToAnim(pendingAnimation, mLauncher, secondTaskEndingBounds, view.getContext()); FloatingTaskView secondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mLauncher, view, bitmap, icon, secondTaskStartingBounds); secondFloatingTaskView.setAlpha(1); Loading Loading @@ -192,6 +196,7 @@ public class SplitToWorkspaceController { private void cleanUp() { mLauncher.getDragLayer().removeView(firstFloatingTaskView); mLauncher.getDragLayer().removeView(secondFloatingTaskView); mLauncher.getDragLayer().removeView(mSplitDividerPlaceholderView); mController.getSplitAnimationController().removeSplitInstructionsView(mLauncher); mController.resetState(); } Loading
quickstep/src/com/android/quickstep/views/FloatingTaskView.java +0 −1 Original line number Diff line number Diff line Loading @@ -299,7 +299,6 @@ public class FloatingTaskView extends FrameLayout { ValueAnimator transitionAnimator = ValueAnimator.ofFloat(0, 1); animation.add(transitionAnimator); long animDuration = animation.getDuration(); RectF floatingTaskViewBounds = new RectF(); if (fadeWithThumbnail) { Loading
quickstep/src/com/android/quickstep/views/RecentsView.java +6 −1 Original line number Diff line number Diff line Loading @@ -61,7 +61,6 @@ import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_RIGHT; import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_TAB; import static com.android.quickstep.util.TaskGridNavHelper.DIRECTION_UP; import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA; import static com.android.window.flags.Flags.enableDesktopWindowingMode; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_ACTIONS_IN_MENU; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_DESKTOP; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION; Loading @@ -69,6 +68,7 @@ import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SELECT_ACTIVE; import static com.android.window.flags.Flags.enableDesktopWindowingMode; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; Loading Loading @@ -721,6 +721,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T private int mSplitHiddenTaskViewIndex = -1; @Nullable private FloatingTaskView mSecondFloatingTaskView; private View mSplitDividerPlaceholderView; /** * The task to be removed and immediately re-added. Should not be added to task pool. Loading Loading @@ -4839,6 +4840,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T mSplitSelectStateController.getActiveSplitStagePosition(), firstTaskEndingBounds, secondTaskEndingBounds); mSplitDividerPlaceholderView = mSplitSelectStateController .getSplitAnimationController().addDividerPlaceholderViewToAnim(pendingAnimation, mActivity, secondTaskEndingBounds, getContext()); FloatingTaskView firstFloatingTaskView = mSplitSelectStateController.getFirstFloatingTaskView(); firstFloatingTaskView.getBoundsOnScreen(firstTaskStartingBounds); Loading Loading @@ -4893,6 +4897,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T safeRemoveDragLayerView(mSplitSelectStateController.getFirstFloatingTaskView()); safeRemoveDragLayerView(mSecondFloatingTaskView); safeRemoveDragLayerView(mSplitSelectStateController.getSplitInstructionsView()); safeRemoveDragLayerView(mSplitDividerPlaceholderView); mSecondFloatingTaskView = null; mSplitSelectSource = null; mSplitSelectStateController.getSplitAnimationController() Loading
res/color/taskbar_background_dark.xml 0 → 100644 +21 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2024 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. --> <!-- Should be the same as in packages/apps/Launcher3/res/color-night-v31/taskbar_background.xml --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- Want to use @android:color/system_neutral1_500, but that causes build errors --> <item android:color="#76777D" android:lStar="6" /> </selector> No newline at end of file