Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fbb9bf1a authored by mattsziklay's avatar mattsziklay Committed by Matt Sziklay
Browse files

Add animations to Manage Windows menu.

Adds animations for opening/closing Manage Windows menu. Also changes
the pivot of the menu on the app header side to be the top left corner
to fit the spec.

Bug: 337915660
Test: Manual
Flag: com.android.window.flags.enable_desktop_windowing_multi_instance_features
Change-Id: I9f47ee95bbeacdd0bf9bc45f336fdee2614045f0
parent 6e7b24e8
Loading
Loading
Loading
Loading
+106 −3
Original line number Diff line number Diff line
@@ -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
        }
    }
}
+6 −5
Original line number Diff line number Diff line
@@ -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()
    }
}
+8 −5
Original line number Diff line number Diff line
@@ -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()
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -1369,7 +1369,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin

    void closeManageWindowsMenu() {
        if (mManageWindowsMenu != null) {
            mManageWindowsMenu.close();
            mManageWindowsMenu.animateClose();
        }
        mManageWindowsMenu = null;
    }
+1 −1
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ class DesktopHeaderManageWindowsMenuTest : ShellTestCase() {

    @After
    fun tearDown() {
        menu.close()
        menu.animateClose()
    }

    @Test