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.intentresolver
18 
19 import android.view.View
20 import android.view.animation.AlphaAnimation
21 import android.view.animation.LinearInterpolator
22 import android.view.animation.Transformation
23 import com.android.intentresolver.chooser.TargetInfo
24 
25 private const val IMAGE_FADE_IN_MILLIS = 150L
26 
27 internal class ItemRevealAnimationTracker {
28     private val iconProgress = HashMap<TargetInfo, Record>()
29     private val labelProgress = HashMap<TargetInfo, Record>()
30 
resetnull31     fun reset() {
32         iconProgress.clear()
33         labelProgress.clear()
34     }
35 
animateIconnull36     fun animateIcon(view: View, info: TargetInfo) = animateView(view, info, iconProgress)
37     fun animateLabel(view: View, info: TargetInfo) = animateView(view, info, labelProgress)
38 
39     private fun animateView(view: View, info: TargetInfo, map: MutableMap<TargetInfo, Record>) {
40         val record = map.getOrPut(info) { Record() }
41         if ((view.animation as? RevealAnimation)?.record === record) return
42 
43         view.clearAnimation()
44         if (record.alpha >= 1f) {
45             view.alpha = 1f
46             return
47         }
48 
49         view.startAnimation(RevealAnimation(record))
50     }
51 
52     private class Record(var alpha: Float = 0f)
53 
54     private class RevealAnimation(val record: Record) : AlphaAnimation(record.alpha, 1f) {
55         init {
56             duration = (IMAGE_FADE_IN_MILLIS * (1f - record.alpha)).toLong()
57             interpolator = LinearInterpolator()
58         }
59 
applyTransformationnull60         override fun applyTransformation(interpolatedTime: Float, t: Transformation) {
61             super.applyTransformation(interpolatedTime, t)
62             // One TargetInfo can be simultaneously bou into multiple UI grid items; make sure
63             // that the alpha value only increases. This should not affect running animations, only
64             // a starting point for a new animation when a different view is bound to this target.
65             record.alpha = minOf(1f, maxOf(record.alpha, t.alpha))
66         }
67     }
68 }
69