1 /* 2 * Copyright (C) 2023 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.systemui.temporarydisplay.chipbar 18 19 import android.view.View 20 import android.view.ViewGroup 21 import com.android.app.animation.Interpolators 22 import com.android.systemui.animation.ViewHierarchyAnimator 23 import com.android.systemui.dagger.SysUISingleton 24 import com.android.systemui.util.children 25 import javax.inject.Inject 26 27 /** 28 * A class controlling chipbar animations. Typically delegates to [ViewHierarchyAnimator]. 29 * 30 * Used so that animations can be mocked out in tests. 31 */ 32 @SysUISingleton 33 open class ChipbarAnimator @Inject constructor() { 34 /** 35 * Animates [innerView] and its children into view. 36 * 37 * @return true if the animation was successfully started and false if the animation can't be 38 * run for any reason. 39 * 40 * See [ViewHierarchyAnimator.animateAddition]. 41 */ animateViewInnull42 open fun animateViewIn(innerView: ViewGroup, onAnimationEnd: Runnable): Boolean { 43 return ViewHierarchyAnimator.animateAddition( 44 innerView, 45 ViewHierarchyAnimator.Hotspot.TOP, 46 Interpolators.EMPHASIZED_DECELERATE, 47 duration = ANIMATION_IN_DURATION, 48 includeMargins = true, 49 includeFadeIn = true, 50 onAnimationEnd = onAnimationEnd, 51 ) 52 } 53 54 /** 55 * Animates [innerView] and its children out of view. 56 * 57 * @return true if the animation was successfully started and false if the animation can't be 58 * run for any reason. 59 * 60 * See [ViewHierarchyAnimator.animateRemoval]. 61 */ animateViewOutnull62 open fun animateViewOut(innerView: ViewGroup, onAnimationEnd: Runnable): Boolean { 63 return ViewHierarchyAnimator.animateRemoval( 64 innerView, 65 ViewHierarchyAnimator.Hotspot.TOP, 66 Interpolators.EMPHASIZED_ACCELERATE, 67 ANIMATION_OUT_DURATION, 68 includeMargins = true, 69 onAnimationEnd, 70 ) 71 } 72 73 /** Force shows this view and all child views. Should be used in case [animateViewIn] fails. */ forceDisplayViewnull74 fun forceDisplayView(innerView: View) { 75 innerView.alpha = 1f 76 if (innerView is ViewGroup) { 77 innerView.children.forEach { forceDisplayView(it) } 78 } 79 } 80 } 81 82 private const val ANIMATION_IN_DURATION = 500L 83 private const val ANIMATION_OUT_DURATION = 250L 84