• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.statusbar.phone.fragment
18 
19 import android.content.res.Resources
20 import android.view.View
21 import androidx.core.animation.Animator
22 import androidx.core.animation.AnimatorSet
23 import androidx.core.animation.ValueAnimator
24 import com.android.systemui.res.R
25 import com.android.systemui.statusbar.events.STATUS_BAR_X_MOVE_IN
26 import com.android.systemui.statusbar.events.STATUS_BAR_X_MOVE_OUT
27 import com.android.systemui.statusbar.events.SystemStatusAnimationCallback
28 import com.android.systemui.util.animation.AnimationUtil.Companion.frames
29 import com.android.systemui.util.doOnCancel
30 import com.android.systemui.util.doOnEnd
31 
32 /**
33  * An implementation of [StatusBarSystemEventDefaultAnimator], applying the onAlphaChanged and
34  * onTranslationXChanged callbacks directly to the provided animatedView.
35  */
36 class StatusBarSystemEventAnimator
37 @JvmOverloads
38 constructor(val animatedView: View, resources: Resources, isAnimationRunning: Boolean = false) :
39     StatusBarSystemEventDefaultAnimator(
40         resources = resources,
41         onAlphaChanged = animatedView::setAlpha,
42         onTranslationXChanged = animatedView::setTranslationX,
43         isAnimationRunning = isAnimationRunning,
44     )
45 
46 /**
47  * Tied directly to [SystemStatusAnimationScheduler]. Any StatusBar-like thing (keyguard, collapsed
48  * status bar fragment), can use this Animator to get the default system status animation. It simply
49  * needs to implement the onAlphaChanged and onTranslationXChanged callbacks.
50  *
51  * This animator relies on resources, and should be recreated whenever resources are updated. While
52  * this class could be used directly as the animation callback, it's probably best to forward calls
53  * to it so that it can be recreated at any moment without needing to remove/add callback.
54  */
55 open class StatusBarSystemEventDefaultAnimator
56 @JvmOverloads
57 constructor(
58     resources: Resources,
59     private val onAlphaChanged: (Float) -> Unit,
60     private val onTranslationXChanged: (Float) -> Unit,
61     var isAnimationRunning: Boolean = false,
62 ) : SystemStatusAnimationCallback {
63     private val translationXIn: Int =
64         resources.getDimensionPixelSize(
65             R.dimen.ongoing_appops_chip_animation_in_status_bar_translation_x
66         )
67     private val translationXOut: Int =
68         resources.getDimensionPixelSize(
69             R.dimen.ongoing_appops_chip_animation_out_status_bar_translation_x
70         )
71 
onSystemEventAnimationBeginnull72     override fun onSystemEventAnimationBegin(): Animator {
73         isAnimationRunning = true
74         return getDefaultStatusBarAnimationForChipEnter(
75             translationXIn,
76             onTranslationXChanged,
77             onAlphaChanged,
78         )
79     }
80 
onSystemEventAnimationFinishnull81     override fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator {
82         onTranslationXChanged(translationXOut.toFloat())
83         val anim =
84             getDefaultStatusBarAnimationForChipExit(
85                 translationXOut,
86                 onTranslationXChanged,
87                 onAlphaChanged,
88             )
89         anim.doOnEnd { isAnimationRunning = false }
90         anim.doOnCancel { isAnimationRunning = false }
91 
92         return anim
93     }
94 
95     /** Static definition of these animations so we can use them more easily from view binders */
96     companion object {
97         /**
98          * Chip: coming in. Animated view: going out.
99          *
100          * Implements the exact spec for animating any status bar elements OUT to make space for the
101          * chip IN animation.
102          */
getDefaultStatusBarAnimationForChipEnternull103         fun getDefaultStatusBarAnimationForChipEnter(
104             targetTranslation: Int,
105             setX: (Float) -> Unit,
106             setAlpha: (Float) -> Unit,
107         ): Animator {
108             val moveOut =
109                 ValueAnimator.ofFloat(0f, 1f).apply {
110                     duration = 23.frames
111                     interpolator = STATUS_BAR_X_MOVE_OUT
112                     addUpdateListener { setX(-(targetTranslation * animatedValue as Float)) }
113                 }
114             val alphaOut =
115                 ValueAnimator.ofFloat(1f, 0f).apply {
116                     duration = 8.frames
117                     interpolator = null
118                     addUpdateListener { setAlpha(animatedValue as Float) }
119                 }
120 
121             val animSet = AnimatorSet()
122             animSet.playTogether(moveOut, alphaOut)
123             return animSet
124         }
125 
126         /**
127          * Chip: going out. Animated view: coming in.
128          *
129          * Implements the exact spec for animating any status bar elements IN as the chip is
130          * animating OUT
131          */
getDefaultStatusBarAnimationForChipExitnull132         fun getDefaultStatusBarAnimationForChipExit(
133             targetTranslation: Int,
134             setX: (Float) -> Unit,
135             setAlpha: (Float) -> Unit,
136         ): Animator {
137             val moveIn =
138                 ValueAnimator.ofFloat(1f, 0f).apply {
139                     duration = 23.frames
140                     startDelay = 7.frames
141                     interpolator = STATUS_BAR_X_MOVE_IN
142                     addUpdateListener { setX(targetTranslation * animatedValue as Float) }
143                 }
144             val alphaIn =
145                 ValueAnimator.ofFloat(0f, 1f).apply {
146                     duration = 5.frames
147                     startDelay = 11.frames
148                     interpolator = null
149                     addUpdateListener { setAlpha(animatedValue as Float) }
150                 }
151 
152             val animatorSet = AnimatorSet()
153             animatorSet.playTogether(moveIn, alphaIn)
154             return animatorSet
155         }
156     }
157 }
158