• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.wm.shell.windowdecor
18 
19 import android.animation.ObjectAnimator
20 import android.view.View
21 import android.view.View.Visibility
22 import android.view.animation.PathInterpolator
23 import android.widget.ImageButton
24 import androidx.core.animation.doOnEnd
25 import com.android.wm.shell.shared.animation.Interpolators
26 
27 /**
28  * Animates the Desktop View's app handle.
29  */
30 class AppHandleAnimator(
31     private val appHandleView: View,
32     private val captionHandle: ImageButton,
33 ) {
34     companion object {
35         //  Constants for animating the whole caption
36         private const val APP_HANDLE_ALPHA_FADE_IN_ANIMATION_DURATION_MS: Long = 275L
37         private const val APP_HANDLE_ALPHA_FADE_OUT_ANIMATION_DURATION_MS: Long = 340
38         private val APP_HANDLE_ANIMATION_INTERPOLATOR = PathInterpolator(
39             0.4f,
40             0f,
41             0.2f,
42             1f
43         )
44 
45         // Constants for animating the caption's handle
46         private const val HANDLE_ANIMATION_DURATION: Long = 100
47         private val HANDLE_ANIMATION_INTERPOLATOR = Interpolators.FAST_OUT_SLOW_IN
48     }
49 
50     private var animator: ObjectAnimator? = null
51 
52     /** Animates the given caption view to the given visibility after a visibility change. */
animateVisibilityChangenull53     fun animateVisibilityChange(@Visibility visible: Int) {
54         when (visible) {
55             View.VISIBLE -> animateShowAppHandle()
56             else -> animateHideAppHandle()
57         }
58     }
59 
60     /** Animate appearance/disappearance of caption's handle. */
animateCaptionHandleAlphanull61     fun animateCaptionHandleAlpha(startValue: Float, endValue: Float) {
62         cancel()
63         animator = ObjectAnimator.ofFloat(captionHandle, View.ALPHA, startValue, endValue).apply {
64             duration = HANDLE_ANIMATION_DURATION
65             interpolator = HANDLE_ANIMATION_INTERPOLATOR
66             start()
67         }
68     }
69 
animateShowAppHandlenull70     private fun animateShowAppHandle() {
71         cancel()
72         appHandleView.alpha = 0f
73         appHandleView.visibility = View.VISIBLE
74         animator = ObjectAnimator.ofFloat(appHandleView, View.ALPHA, 1f).apply {
75             duration = APP_HANDLE_ALPHA_FADE_IN_ANIMATION_DURATION_MS
76             interpolator = APP_HANDLE_ANIMATION_INTERPOLATOR
77             start()
78         }
79     }
80 
animateHideAppHandlenull81     private fun animateHideAppHandle() {
82         cancel()
83         animator = ObjectAnimator.ofFloat(appHandleView, View.ALPHA, 0f).apply {
84             duration = APP_HANDLE_ALPHA_FADE_OUT_ANIMATION_DURATION_MS
85             interpolator = APP_HANDLE_ANIMATION_INTERPOLATOR
86             doOnEnd {
87                 appHandleView.visibility = View.GONE
88             }
89             start()
90         }
91     }
92 
93     /**
94      * Cancels any active animations.
95      */
cancelnull96     fun cancel() {
97         animator?.removeAllListeners()
98         animator?.cancel()
99         animator = null
100     }
101 }
102