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.statusbar.phone.fragment
18 
19 import android.view.View
20 import androidx.core.animation.Interpolator
21 import androidx.core.animation.ValueAnimator
22 import com.android.app.animation.InterpolatorsAndroidX
23 
24 /**
25  * A controller that keeps track of multiple sources applying alpha value changes to a view. It will
26  * always apply the minimum alpha value of all sources.
27  */
28 internal class MultiSourceMinAlphaController
29 @JvmOverloads
30 constructor(private val view: View, private val initialAlpha: Float = 1f) {
31 
32     private val alphas = mutableMapOf<Int, Float>()
33     private val animators = mutableMapOf<Int, ValueAnimator>()
34 
35     /**
36      * Sets the alpha of the provided source and applies it to the view (if no other source has set
37      * a lower alpha currently). If an animator of the same source is still running (i.e.
38      * [animateToAlpha] was called before), that animator is cancelled.
39      */
setAlphanull40     fun setAlpha(alpha: Float, sourceId: Int) {
41         animators[sourceId]?.cancel()
42         updateAlpha(alpha, sourceId)
43     }
44 
45     /** Animates to the alpha of the provided source. */
animateToAlphanull46     fun animateToAlpha(
47         alpha: Float,
48         sourceId: Int,
49         duration: Long,
50         interpolator: Interpolator = InterpolatorsAndroidX.ALPHA_IN,
51         startDelay: Long = 0
52     ) {
53         animators[sourceId]?.cancel()
54         val animator = ValueAnimator.ofFloat(getMinAlpha(), alpha)
55         animator.duration = duration
56         animator.startDelay = startDelay
57         animator.interpolator = interpolator
58         animator.addUpdateListener { updateAlpha(animator.animatedValue as Float, sourceId) }
59         animator.start()
60         animators[sourceId] = animator
61     }
62 
resetnull63     fun reset() {
64         alphas.clear()
65         animators.forEach { it.value.cancel() }
66         animators.clear()
67         applyAlphaToView()
68     }
69 
updateAlphanull70     private fun updateAlpha(alpha: Float, sourceId: Int) {
71         alphas[sourceId] = alpha
72         applyAlphaToView()
73     }
74 
applyAlphaToViewnull75     private fun applyAlphaToView() {
76         val minAlpha = getMinAlpha()
77         view.visibility = if (minAlpha != 0f) View.VISIBLE else View.INVISIBLE
78         view.alpha = minAlpha
79     }
80 
<lambda>null81     private fun getMinAlpha() = alphas.minOfOrNull { it.value } ?: initialAlpha
82 }
83