diff options
5 files changed, 122 insertions, 15 deletions
diff --git a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/ManageWindowsViewContainer.kt b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/ManageWindowsViewContainer.kt index 0e8e90467745..23e7441ff86b 100644 --- a/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/ManageWindowsViewContainer.kt +++ b/libs/WindowManager/Shell/shared/src/com/android/wm/shell/shared/desktopmode/ManageWindowsViewContainer.kt @@ -15,6 +15,10 @@ */ package com.android.wm.shell.shared.desktopmode +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.animation.AnimatorSet +import android.animation.ObjectAnimator import android.annotation.ColorInt import android.content.Context import android.graphics.Bitmap @@ -23,6 +27,10 @@ import android.graphics.drawable.shapes.RoundRectShape import android.util.TypedValue import android.view.MotionEvent.ACTION_OUTSIDE import android.view.SurfaceView +import android.view.View +import android.view.View.ALPHA +import android.view.View.SCALE_X +import android.view.View.SCALE_Y import android.view.ViewGroup.MarginLayoutParams import android.widget.LinearLayout import android.window.TaskSnapshot @@ -39,7 +47,7 @@ abstract class ManageWindowsViewContainer( lateinit var menuView: ManageWindowsView /** Creates the base menu view and fills it with icon views. */ - fun show(snapshotList: List<Pair<Int, TaskSnapshot>>, + fun createMenu(snapshotList: List<Pair<Int, TaskSnapshot>>, onIconClickListener: ((Int) -> Unit), onOutsideClickListener: (() -> Unit)): ManageWindowsView { menuView = ManageWindowsView(context, menuBackgroundColor).apply { @@ -51,11 +59,24 @@ abstract class ManageWindowsViewContainer( return menuView } + /** Play the animation for opening the menu. */ + fun animateOpen() { + menuView.animateOpen() + } + + /** + * Play the animation for closing the menu. On finish, will run the provided callback, + * which will be responsible for removing the view from the container used in [addToContainer]. + */ + fun animateClose() { + menuView.animateClose { removeFromContainer() } + } + /** Adds the menu view to the container responsible for displaying it. */ abstract fun addToContainer(menuView: ManageWindowsView) - /** Dispose of the menu, perform needed cleanup. */ - abstract fun close() + /** Removes the menu view from the container used in the method above */ + abstract fun removeFromContainer() companion object { const val MANAGE_WINDOWS_MINIMUM_INSTANCES = 2 @@ -65,6 +86,8 @@ abstract class ManageWindowsViewContainer( private val context: Context, menuBackgroundColor: Int ) { + private val animators = mutableListOf<Animator>() + private val iconViews = mutableListOf<SurfaceView>() val rootView: LinearLayout = LinearLayout(context) var menuHeight = 0 var menuWidth = 0 @@ -147,6 +170,7 @@ abstract class ManageWindowsViewContainer( menuWidth += (instanceIconWidth + iconMargin).toInt() } rowLayout?.addView(appSnapshotButton) + iconViews += appSnapshotButton appSnapshotButton.requestLayout() rowLayout?.post { appSnapshotButton.holder.surface @@ -190,6 +214,78 @@ abstract class ManageWindowsViewContainer( } } + /** Play the animation for opening the menu. */ + fun animateOpen() { + animateView(rootView, MENU_BOUNDS_SHRUNK_SCALE, MENU_BOUNDS_FULL_SCALE, + MENU_START_ALPHA, MENU_FULL_ALPHA) + for (view in iconViews) { + animateView(view, MENU_BOUNDS_SHRUNK_SCALE, MENU_BOUNDS_FULL_SCALE, + MENU_START_ALPHA, MENU_FULL_ALPHA) + } + createAnimatorSet().start() + } + + /** Play the animation for closing the menu. */ + fun animateClose(callback: () -> Unit) { + animateView(rootView, MENU_BOUNDS_FULL_SCALE, MENU_BOUNDS_SHRUNK_SCALE, + MENU_FULL_ALPHA, MENU_START_ALPHA) + for (view in iconViews) { + animateView(view, MENU_BOUNDS_FULL_SCALE, MENU_BOUNDS_SHRUNK_SCALE, + MENU_FULL_ALPHA, MENU_START_ALPHA) + } + createAnimatorSet().apply { + addListener( + object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator) { + callback.invoke() + } + } + ) + start() + } + } + + private fun animateView( + view: View, + startBoundsScale: Float, + endBoundsScale: Float, + startAlpha: Float, + endAlpha: Float) { + animators += ObjectAnimator.ofFloat( + view, + SCALE_X, + startBoundsScale, + endBoundsScale + ).apply { + duration = MENU_BOUNDS_ANIM_DURATION + } + animators += ObjectAnimator.ofFloat( + view, + SCALE_Y, + startBoundsScale, + endBoundsScale + ).apply { + duration = MENU_BOUNDS_ANIM_DURATION + } + animators += ObjectAnimator.ofFloat( + view, + ALPHA, + startAlpha, + endAlpha + ).apply { + duration = MENU_ALPHA_ANIM_DURATION + startDelay = MENU_ALPHA_ANIM_DELAY + } + } + + private fun createAnimatorSet(): AnimatorSet { + val animatorSet = AnimatorSet().apply { + playTogether(animators) + } + animators.clear() + return animatorSet + } + companion object { private const val MENU_RADIUS_DP = 26f private const val ICON_WIDTH_DP = 204f @@ -198,6 +294,13 @@ abstract class ManageWindowsViewContainer( private const val ICON_MARGIN_DP = 16f private const val MENU_ELEVATION_DP = 1f private const val MENU_MAX_ICONS_PER_ROW = 3 + private const val MENU_BOUNDS_ANIM_DURATION = 200L + private const val MENU_BOUNDS_SHRUNK_SCALE = 0.8f + private const val MENU_BOUNDS_FULL_SCALE = 1f + private const val MENU_ALPHA_ANIM_DURATION = 100L + private const val MENU_ALPHA_ANIM_DELAY = 50L + private const val MENU_START_ALPHA = 0f + private const val MENU_FULL_ALPHA = 1f } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopHandleManageWindowsMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopHandleManageWindowsMenu.kt index e71b4f3abf14..7b71e41874c7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopHandleManageWindowsMenu.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopHandleManageWindowsMenu.kt @@ -53,11 +53,8 @@ class DesktopHandleManageWindowsMenu( private var menuViewContainer: AdditionalViewContainer? = null init { - show(snapshotList, onIconClickListener, onOutsideClickListener) - } - - override fun close() { - menuViewContainer?.releaseView() + createMenu(snapshotList, onIconClickListener, onOutsideClickListener) + animateOpen() } private fun calculateMenuPosition(): Point { @@ -106,4 +103,8 @@ class DesktopHandleManageWindowsMenu( view = menuView.rootView, ) } + + override fun removeFromContainer() { + menuViewContainer?.releaseView() + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenu.kt index 173bc08970ca..dd68105d28c1 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenu.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenu.kt @@ -65,11 +65,10 @@ class DesktopHeaderManageWindowsMenu( var menuViewContainer: AdditionalViewContainer? = null init { - show(snapshotList, onIconClickListener, onOutsideClickListener) - } - - override fun close() { - menuViewContainer?.releaseView() + createMenu(snapshotList, onIconClickListener, onOutsideClickListener) + menuView.rootView.pivotX = 0f + menuView.rootView.pivotY = 0f + animateOpen() } override fun addToContainer(menuView: ManageWindowsView) { @@ -139,4 +138,8 @@ class DesktopHeaderManageWindowsMenu( surfaceControlTransactionSupplier ) } + + override fun removeFromContainer() { + menuViewContainer?.releaseView() + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java index dc27cfe9e35f..9f37358b6044 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java @@ -1452,7 +1452,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin void closeManageWindowsMenu() { if (mManageWindowsMenu != null) { - mManageWindowsMenu.close(); + mManageWindowsMenu.animateClose(); } mManageWindowsMenu = null; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenuTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenuTest.kt index f9f760e3f482..cb8c74307449 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenuTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopHeaderManageWindowsMenuTest.kt @@ -70,7 +70,7 @@ class DesktopHeaderManageWindowsMenuTest : ShellTestCase() { @After fun tearDown() { - menu.close() + menu.animateClose() } @Test |