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