• 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.permissioncontroller.safetycenter.ui
18 
19 import android.transition.AutoTransition
20 import android.transition.Transition
21 import android.transition.TransitionListenerAdapter
22 import android.transition.TransitionManager
23 import android.transition.TransitionSet
24 import android.view.View
25 import android.view.ViewGroup
26 import android.view.animation.LinearInterpolator
27 import android.widget.TextView
28 import java.time.Duration
29 
30 /**
31  * An animator which can animate a fade in/fade out of either one textView, or several textViews
32  * that are in the same ViewGroup.
33  */
34 class TextFadeAnimator
35 @JvmOverloads
36 constructor(targetIds: List<Int>, changeDuration: Duration = DEFAULT_TEXT_CHANGE_DURATION) {
37 
38     @JvmOverloads
39     constructor(
40         targetId: Int,
41         changeDuration: Duration = DEFAULT_TEXT_CHANGE_DURATION
42     ) : this(listOf(targetId), changeDuration)
43 
44     private val textChangeTransition: TransitionSet
45     init {
46         var transition =
47             AutoTransition()
48                 .setInterpolator(linearInterpolator)
49                 .setDuration(changeDuration.toMillis())
50         for (targetId in targetIds) {
51             transition = transition.addTarget(targetId)
52         }
53         textChangeTransition = transition
54     }
55 
56     @JvmOverloads
animateChangeTextnull57     fun animateChangeText(textView: TextView, text: String, onFinish: Runnable? = null) {
58         animateChangeText(listOf(textView to text), onFinish)
59     }
60 
61     /** Animate changes for a set of textViews under the same parent. */
62     @JvmOverloads
animateChangeTextnull63     fun animateChangeText(textChanges: List<Pair<TextView, String>>, onFinish: Runnable? = null) {
64         if (textChanges.isEmpty()) {
65             return
66         }
67         val firstView = textChanges[0].first
68         val parentViewGroup: ViewGroup = firstView.parent as ViewGroup
69         val fadeOutTransition =
70             textChangeTransition
71                 .clone()
72                 .addListener(
73                     object : TransitionListenerAdapter() {
74                         override fun onTransitionStart(transition: Transition?) {
75                             super.onTransitionStart(transition)
76                         }
77                         override fun onTransitionEnd(transition: Transition?) {
78                             super.onTransitionEnd(transition)
79                             fadeTextIn(textChanges, parentViewGroup, onFinish)
80                         }
81                     })
82         parentViewGroup.post {
83             TransitionManager.beginDelayedTransition(parentViewGroup, fadeOutTransition)
84             for ((textView, _) in textChanges) {
85                 textView.visibility = View.INVISIBLE
86             }
87         }
88     }
89 
fadeTextInnull90     private fun fadeTextIn(
91         textChanges: List<Pair<TextView, String>>,
92         parent: ViewGroup,
93         onFinish: Runnable?
94     ) {
95         val fadeInTransition =
96             textChangeTransition
97                 .clone()
98                 .addListener(
99                     object : TransitionListenerAdapter() {
100                         override fun onTransitionEnd(transition: Transition?) {
101                             super.onTransitionEnd(transition)
102                             onFinish?.run()
103                         }
104                     })
105 
106         parent.post {
107             TransitionManager.beginDelayedTransition(parent, fadeInTransition)
108             for ((textView, text) in textChanges) {
109                 textView.text = text
110                 textView.visibility = View.VISIBLE
111             }
112         }
113     }
114 
cancelTextChangeAnimationnull115     fun cancelTextChangeAnimation(textView: TextView) {
116         TransitionManager.endTransitions(textView.parent as ViewGroup)
117     }
118 
119     companion object {
120         // Duration is for fade-out & fade-in individually, not combined
121         private val DEFAULT_TEXT_CHANGE_DURATION = Duration.ofMillis(167)
122         private val linearInterpolator = LinearInterpolator()
123     }
124 }
125